Advertisements

Cognitive Services : Extract handwritten text from an image using Computer Vision API With ASP.NET Core & C#


Introduction

In this article, we are going to learn how to extract handwritten text from an image using one of the important Cognitive Services API called Computer Vision API. So, we need a valid subscription key for accessing this feature. So before reading this article, you must read our previous articles related to Computer Vision API because we have explained other features of Computer Vision API in our previous article. This technology is currently in preview and is only available for English text.

Before reading this article, you must read the articles given below for Computer Vision API Knowledge.

Prerequisites

  1. Subscription key ( Azure Portal ).
  2. Visual Studio 2015 or 2017

Subscription Key Free Trail

If you don’t have Microsoft Azure Subscription and want to test the Computer Vision API because it requires a valid Subscription key for processing the image information. Don’t worry !! Microsoft gives a 7 day trial Subscription Key ( Click here ). We can use that Subscription key for testing purposes. If you sign up using the Computer Vision free trial, then your subscription keys are valid for the westcentral region (https://westcentralus.api.cognitive.microsoft.com ).

Requirements

These are the major requirements mentioned in the Microsoft docs.

  1. Supported input methods: Raw image binary in the form of an application/octet stream or image URL.
  2. Supported image formats: JPEG, PNG, BMP.
  3. Image file size: Less than 4 MB.
  4. Image dimensions must be at least 40 x 40, at most 3200 x 3200.

Computer Vision API

First, we need to log into the Azure Portal with our Azure credentials. Then we need to create an Azure Computer Vision Subscription Key in the Azure portal.

Click on “Create a resource” on the left side menu and it will open an “Azure Marketplace”. There, we can see the list of services. Click “AI + Machine Learning” then click on the “Computer Vision”.

Provision a Computer Vision Subscription Key

After clicking the “Computer Vision”, It will open another section. There, we need to provide the basic information about Computer Vision API.

Name : Name of the Computer Vision API ( Eg. HandwrittenApp ).

Subscription : We can select our Azure subscription for Computer Vision API creation.

Location : We can select our location of resource group. The best thing is we can choose a location closest to our customer.

Pricing tier : Select an appropriate pricing tier for our requirement.

Resource group : We can create a new resource group or choose from an existing one.

Now click on the “HandwrittenApp” in dashboard page and it will redirect to the details page of HandwrittenApp ( “Overview” ). Here, we can see the Manage Key ( Subscription key details ) & Endpoint details. Click on the “Show access keys…” links and it will redirect to another page.

We can use any of the subscription keys or regenerate the given key for getting image information using Computer Vision API.

Endpoint

As we mentioned above the location is the same for all the free trial Subscription Keys. In Azure we can choose available locations while creating a Computer Vision API. We have used the following endpoint in our code.

https://westus.api.cognitive.microsoft.com/vision/v1.0/recognizeText

View Model

The following model contains the API image response information.

using System.Collections.Generic;

namespace HandwrittenTextApp.Models
{
public class Word
{
public List<int> boundingBox { get; set; }
public string text { get; set; }
}

public class Line
{
public List<int> boundingBox { get; set; }
public string text { get; set; }
public List<Word> words { get; set; }
}

public class RecognitionResult
{
public List<Line> lines { get; set; }
}

public class ImageInfoViewModel
{
public string status { get; set; }
public RecognitionResult recognitionResult { get; set; }
}
}

Request URL

We can add additional parameters or request parameters ( optional ) in our API “endPoint” and it will provide more information for the given image.

https://westus.api.cognitive.microsoft.com/vision/v1.0/recognizeText%5B?mode%5D

Request parameters

These are the following optional parameters available in Computer Vision API.

  1. mode

mode

The mode will be different for different versions of Vision API. So don’t get confused while we are using Version v1 that is given in our Azure portal. If this parameter is set to “Printed”, printed text recognition is performed. If “Handwritten” is specified, handwriting recognition is performed. (Note: This parameter is case sensitive.) This is a required parameter and cannot be empty.

Interface

The “IVisionApiService” contains two signatures for processing or extracting handwritten content in an image. So we have injected this interface in the ASP.NET Core “Startup.cs” class as a “AddTransient”.

using System.Threading.Tasks;

namespace HandwrittenTextApp.Business_Layer.Interface
{
interface IVisionApiService
{
Task<string> ReadHandwrittenText();
byte[] GetImageAsByteArray(string imageFilePath);
}
}

Vision API Service

The following code will process and generate image information using Computer Vision API and its response is mapped into the “ImageInfoViewModel”. We can add the valid Computer Vision API Subscription Key into the following code.

using HandwrittenTextApp.Business_Layer.Interface;
using HandwrittenTextApp.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace HandwrittenTextApp.Business_Layer
{
public class VisionApiService : IVisionApiService
{
// Replace <Subscription Key> with your valid subscription key.
const string subscriptionKey = "<Subscription Key>";

// You must use the same region in your REST call as you used to
// get your subscription keys. The paid subscription keys you will get
// it from microsoft azure portal.
// Free trial subscription keys are generated in the westcentralus region.
// If you use a free trial subscription key, you shouldn't need to change
// this region.
const string endPoint =
"https://westus.api.cognitive.microsoft.com/vision/v1.0/recognizeText";

///
<summary>
/// Gets the handwritten text from the specified image file by using
/// the Computer Vision REST API.
/// </summary>

/// <param name="imageFilePath">The image file with handwritten text.</param>
public async Task<string> ReadHandwrittenText()
{
string imageFilePath = @"C:\Users\rajeesh.raveendran\Desktop\vaisakh.jpg";
var errors = new List<string>();
ImageInfoViewModel responeData = new ImageInfoViewModel();
string extractedResult = "";
try
{
HttpClient client = new HttpClient();

// Request headers.
client.DefaultRequestHeaders.Add(
"Ocp-Apim-Subscription-Key", subscriptionKey);

// Request parameter.
// Note: The request parameter changed for APIv2.
// For APIv1, it is "handwriting=true".
string requestParameters = "mode=Handwritten";

// Assemble the URI for the REST API Call.
string uri = endPoint + "?" + requestParameters;

HttpResponseMessage response;

// Two REST API calls are required to extract handwritten text.
// One call to submit the image for processing, the other call
// to retrieve the text found in the image.
// operationLocation stores the REST API location to call to
// retrieve the text.
string operationLocation;

// Request body.
// Posts a locally stored JPEG image.
byte[] byteData = GetImageAsByteArray(imageFilePath);

using (ByteArrayContent content = new ByteArrayContent(byteData))
{
// This example uses content type "application/octet-stream".
// The other content types you can use are "application/json"
// and "multipart/form-data".
content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");

// The first REST call starts the async process to analyze the
// written text in the image.
response = await client.PostAsync(uri, content);
}

// The response contains the URI to retrieve the result of the process.
if (response.IsSuccessStatusCode)
operationLocation =
response.Headers.GetValues("Operation-Location").FirstOrDefault();
else
{
// Display the JSON error data.
string errorString = await response.Content.ReadAsStringAsync();
//Console.WriteLine("\n\nResponse:\n{0}\n",
// JToken.Parse(errorString).ToString());
return errorString;
}

// The second REST call retrieves the text written in the image.
//
// Note: The response may not be immediately available. Handwriting
// recognition is an async operation that can take a variable amount
// of time depending on the length of the handwritten text. You may
// need to wait or retry this operation.
//
// This example checks once per second for ten seconds.
string result;
int i = 0;
do
{
System.Threading.Thread.Sleep(1000);
response = await client.GetAsync(operationLocation);
result = await response.Content.ReadAsStringAsync();
++i;
}
while (i < 10 && result.IndexOf("\"status\":\"Succeeded\"") == -1);

if (i == 10 && result.IndexOf("\"status\":\"Succeeded\"") == -1)
{
Console.WriteLine("\nTimeout error.\n");
return "Error";
}

//If it is success it will execute further process.
if (response.IsSuccessStatusCode)
{
// The JSON response mapped into respective view model.
responeData = JsonConvert.DeserializeObject<ImageInfoViewModel>(result,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include,
Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs earg)
{
errors.Add(earg.ErrorContext.Member.ToString());
earg.ErrorContext.Handled = true;
}
}
);

var linesCount = responeData.recognitionResult.lines.Count;
for (int j = 0; j < linesCount; j++)
{
var imageText = responeData.recognitionResult.lines[j].text;

extractedResult += imageText + Environment.NewLine;
}

}
}
catch (Exception e)
{
Console.WriteLine("\n" + e.Message);
}
return extractedResult;
}

///
<summary>
/// Returns the contents of the specified file as a byte array.
/// </summary>

/// <param name="imageFilePath">The image file to read.</param>
/// <returns>The byte array of the image data.</returns>
public byte[] GetImageAsByteArray(string imageFilePath)
{
using (FileStream fileStream =
new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
BinaryReader binaryReader = new BinaryReader(fileStream);
return binaryReader.ReadBytes((int)fileStream.Length);
}
}
}
}

API Response – Based on the given Image

The successful json response.

{
"status": "Succeeded",
"recognitionResult": {
"lines": [
{
"boundingBox": [
170,
34,
955,
31,
956,
78,
171,
81
],
"text": "Memories ! are born not made !",
"words": [
{
"boundingBox": [
158,
33,
378,
33,
373,
81,
153,
81
],
"text": "Memories"
},
{
"boundingBox": [
359,
33,
407,
33,
402,
81,
354,
81
],
"text": "!"
},
{
"boundingBox": [
407,
33,
508,
33,
503,
81,
402,
81
],
"text": "are"
},
{
"boundingBox": [
513,
33,
662,
33,
657,
81,
508,
81
],
"text": "born"
},
{
"boundingBox": [
676,
33,
786,
33,
781,
81,
671,
81
],
"text": "not"
},
{
"boundingBox": [
786,
33,
940,
33,
935,
81,
781,
81
],
"text": "made"
},
{
"boundingBox": [
926,
33,
974,
33,
969,
81,
921,
81
],
"text": "!"
}
]
},
{
"boundingBox": [
181,
121,
918,
112,
919,
175,
182,
184
],
"text": "Bloom of roses to my heart",
"words": [
{
"boundingBox": [
162,
123,
307,
121,
298,
185,
154,
187
],
"text": "Bloom"
},
{
"boundingBox": [
327,
120,
407,
119,
398,
183,
318,
185
],
"text": "of"
},
{
"boundingBox": [
422,
119,
572,
117,
563,
181,
413,
183
],
"text": "roses"
},
{
"boundingBox": [
577,
117,
647,
116,
638,
180,
568,
181
],
"text": "to"
},
{
"boundingBox": [
647,
116,
742,
115,
733,
179,
638,
180
],
"text": "my"
},
{
"boundingBox": [
757,
115,
927,
113,
918,
177,
748,
179
],
"text": "heart"
}
]
},
{
"boundingBox": [
190,
214,
922,
201,
923,
254,
191,
267
],
"text": "Sometimes lonely field as",
"words": [
{
"boundingBox": [
178,
213,
468,
209,
467,
263,
177,
267
],
"text": "Sometimes"
},
{
"boundingBox": [
486,
209,
661,
206,
660,
260,
485,
263
],
"text": "lonely"
},
{
"boundingBox": [
675,
206,
840,
203,
839,
257,
674,
260
],
"text": "field"
},
{
"boundingBox": [
850,
203,
932,
202,
931,
256,
848,
257
],
"text": "as"
}
]
},
{
"boundingBox": [
187,
304,
560,
292,
561,
342,
188,
354
],
"text": "sky kisses it",
"words": [
{
"boundingBox": [
173,
302,
288,
300,
288,
353,
173,
355
],
"text": "sky"
},
{
"boundingBox": [
288,
300,
488,
295,
488,
348,
288,
353
],
"text": "kisses"
},
{
"boundingBox": [
488,
295,
573,
293,
573,
346,
488,
348
],
"text": "it"
}
]
},
{
"boundingBox": [
191,
417,
976,
387,
979,
469,
194,
499
],
"text": "Three years iam gifted with",
"words": [
{
"boundingBox": [
173,
417,
324,
412,
318,
494,
167,
499
],
"text": "Three"
},
{
"boundingBox": [
343,
411,
504,
405,
498,
488,
337,
493
],
"text": "years"
},
{
"boundingBox": [
517,
405,
623,
401,
617,
483,
512,
487
],
"text": "iam"
},
{
"boundingBox": [
646,
400,
839,
394,
833,
476,
640,
483
],
"text": "gifted"
},
{
"boundingBox": [
839,
394,
977,
389,
971,
471,
833,
476
],
"text": "with"
}
]
},
{
"boundingBox": [
167,
492,
825,
472,
828,
551,
169,
572
],
"text": "gud friend happiness !",
"words": [
{
"boundingBox": [
159,
493,
274,
489,
274,
569,
159,
573
],
"text": "gud"
},
{
"boundingBox": [
284,
489,
484,
483,
484,
563,
284,
569
],
"text": "friend"
},
{
"boundingBox": [
504,
482,
814,
473,
814,
553,
504,
562
],
"text": "happiness"
},
{
"boundingBox": [
794,
474,
844,
472,
844,
552,
794,
554
],
"text": "!"
}
]
},
{
"boundingBox": [
167,
608,
390,
628,
387,
664,
163,
644
],
"text": "50870 W,",
"words": [
{
"boundingBox": [
159,
603,
321,
623,
310,
661,
147,
641
],
"text": "50870"
},
{
"boundingBox": [
309,
621,
409,
634,
397,
672,
297,
659
],
"text": "W,"
}
]
},
{
"boundingBox": [
419,
607,
896,
601,
897,
665,
420,
671
],
"text": "Seperation , sheds",
"words": [
{
"boundingBox": [
404,
609,
713,
604,
707,
669,
399,
674
],
"text": "Seperation"
},
{
"boundingBox": [
703,
604,
749,
604,
743,
669,
698,
669
],
"text": ","
},
{
"boundingBox": [
740,
604,
910,
602,
904,
667,
734,
669
],
"text": "sheds"
}
]
},
{
"boundingBox": [
161,
685,
437,
688,
436,
726,
160,
724
],
"text": "blood as in",
"words": [
{
"boundingBox": [
147,
687,
299,
684,
291,
726,
139,
729
],
"text": "blood"
},
{
"boundingBox": [
311,
683,
387,
682,
379,
724,
303,
725
],
"text": "as"
},
{
"boundingBox": [
398,
681,
440,
681,
432,
723,
390,
724
],
"text": "in"
}
]
},
{
"boundingBox": [
518,
678,
686,
679,
685,
719,
517,
718
],
"text": "tears !",
"words": [
{
"boundingBox": [
518,
677,
678,
682,
665,
723,
505,
717
],
"text": "tears"
},
{
"boundingBox": [
658,
681,
708,
683,
695,
724,
645,
722
],
"text": "!"
}
]
},
{
"boundingBox": [
165,
782,
901,
795,
900,
868,
164,
855
],
"text": "I can't bear it Especially",
"words": [
{
"boundingBox": [
145,
785,
191,
786,
184,
862,
138,
861
],
"text": "I"
},
{
"boundingBox": [
204,
786,
342,
787,
336,
863,
198,
862
],
"text": "can't"
},
{
"boundingBox": [
370,
788,
513,
789,
506,
865,
364,
864
],
"text": "bear"
},
{
"boundingBox": [
522,
789,
595,
790,
589,
866,
516,
865
],
"text": "it"
},
{
"boundingBox": [
605,
790,
913,
794,
907,
869,
598,
866
],
"text": "Especially"
}
]
},
{
"boundingBox": [
165,
874,
966,
884,
965,
942,
164,
933
],
"text": "final year a bunch of white",
"words": [
{
"boundingBox": [
155,
872,
306,
875,
294,
936,
143,
933
],
"text": "final"
},
{
"boundingBox": [
331,
876,
457,
878,
445,
939,
320,
936
],
"text": "year"
},
{
"boundingBox": [
466,
878,
508,
879,
496,
940,
454,
939
],
"text": "a"
},
{
"boundingBox": [
525,
879,
676,
882,
664,
943,
513,
940
],
"text": "bunch"
},
{
"boundingBox": [
697,
882,
772,
884,
760,
945,
685,
943
],
"text": "of"
},
{
"boundingBox": [
785,
884,
970,
888,
958,
948,
773,
945
],
"text": "white"
}
]
},
{
"boundingBox": [
174,
955,
936,
960,
935,
1006,
173,
1001
],
"text": "roses to me . I Loved it ! !",
"words": [
{
"boundingBox": [
164,
953,
348,
954,
341,
1002,
157,
1001
],
"text": "roses"
},
{
"boundingBox": [
376,
955,
445,
955,
437,
1003,
368,
1003
],
"text": "to"
},
{
"boundingBox": [
449,
955,
537,
956,
529,
1004,
442,
1003
],
"text": "me"
},
{
"boundingBox": [
518,
956,
564,
957,
557,
1005,
511,
1004
],
"text": "."
},
{
"boundingBox": [
569,
957,
615,
957,
607,
1005,
561,
1005
],
"text": "I"
},
{
"boundingBox": [
629,
957,
799,
959,
791,
1007,
621,
1005
],
"text": "Loved"
},
{
"boundingBox": [
817,
959,
886,
960,
879,
1008,
810,
1007
],
"text": "it"
},
{
"boundingBox": [
881,
960,
927,
960,
920,
1008,
874,
1008
],
"text": "!"
},
{
"boundingBox": [
909,
960,
955,
960,
948,
1008,
902,
1008
],
"text": "!"
}
]
},
{
"boundingBox": [
613,
1097,
680,
1050,
702,
1081,
635,
1129
],
"text": "by",
"words": [
{
"boundingBox": [
627,
1059,
683,
1059,
681,
1107,
625,
1107
],
"text": "by"
}
]
},
{
"boundingBox": [
320,
1182,
497,
1191,
495,
1234,
318,
1224
],
"text": "Vaisak",
"words": [
{
"boundingBox": [
309,
1183,
516,
1186,
492,
1229,
286,
1227
],
"text": "Vaisak"
}
]
},
{
"boundingBox": [
582,
1186,
964,
1216,
961,
1264,
578,
1234
],
"text": "Viswanathan",
"words": [
{
"boundingBox": [
574,
1186,
963,
1218,
945,
1265,
556,
1232
],
"text": "Viswanathan"
}
]
},
{
"boundingBox": [
289,
1271,
997,
1279,
996,
1364,
288,
1356
],
"text": "( Menonpara, Palakkad )",
"words": [
{
"boundingBox": [
274,
1264,
324,
1265,
306,
1357,
256,
1356
],
"text": "("
},
{
"boundingBox": [
329,
1265,
679,
1273,
661,
1364,
311,
1357
],
"text": "Menonpara,"
},
{
"boundingBox": [
669,
1273,
979,
1279,
961,
1371,
651,
1364
],
"text": "Palakkad"
},
{
"boundingBox": [
969,
1279,
1019,
1280,
1001,
1371,
951,
1370
],
"text": ")"
}
]
}
]
}
}

Download

Output

Handwritten content from an image using Computer Vision API. The content is extracted (around 99.99%) from the given image. If any failure occurs in detecting the image,it means that the Vision algorithm is not able to identify the written content.

Note : Thank you Vaisakh Viswanathan ( The author of the peom ).

Reference

See Also

You can download other ASP.NET Core source codes from MSDN Code, using the link, mentioned below.

Summary

From this article we have learned extract handwritten content from an image using One of the important Cognitive Services API ( Computer Vision API ). I hope this article is useful for all Azure Cognitive Services API beginners.

Advertisements

Create & Deploy an ASP.NET Core web app in Azure


Introduction

Nowadays, most people are choosing web hosting on a cloud platform. Microsoft lovers like us basically select “Microsoft Azure” as our hosting environment.That’s the reason I have written this new article defining a simple way of hosting in Azure.

Before reading this article, you must read the articles given below for ASP.NET Core knowledge.

Azure Account 

First, we need to create an account on the Azure portal. Only then can we host the application in the cloud environment. So, please check the following steps to create an Azure account.

Azure Account Registration

Create an account through this link to Azure Portal.

Domain Registration

We need to host our application in a particular domain. Check the following steps –

  1. Click on “All resources” on the left side menu and it will open a dashboard with an empty or already existing list of resources that we have created earlier.
  2. Click on the “Add” button and it will open another window with multiple options. We can choose an appropriate option to host our application.
  3. As per our requirement, we choose “Web + Mobile” and clicked on the “Web App” on the right side.
App Name Creation

App Name Creation

4. It will open another form to fill up our app details to host. We need to give a unique name in the “Appname” section and It will create a subdomain for our ASP.NET Core application.

5. We choose subscription as “Free Trial” because we created a free account on the Azure portal.

6. We need to host our app resources in Resource group, So first we need to create a resource group name in our Azure account. But we choose existing resource group name “AzureDemo” that we are already created in our Azure account.

7.”OS ( Operating System )” we selected as “Windows”( As per our requirement ).

8. We can create our own App Service Plan name.

9. Application Insight will give you the more clarity about your hosted app. Eg. analytics, etc.

10. Click on the “Create” button and wait for the build success.

Resource Group Name

Resource Group Name

11. Another way to create the Resource Group Name – click on “Resource groups -> Add”.

Resource Group

Resource Group

12. Once the build is succeeded, then we can see this output.

Build Succeeded

Simple steps to create an Asp.Net Core Application

  1. Open our  VisualStudio then click on File > New > Project.
  2. Select Visual C# > Web > ASP.NET Core Web Application.
  3. We have given our application name as “MyFirstAzureWebApp”.
  4. Then, click OK.
  5. Click on the “Ctrl+F5”

App Publishing into Azure
We created a default ASP.NET Core application ( We have done some changes in UI Section) for the publishing process.

  1. Right click on the application and click on the Publish menu.
App Publishing

App Publishing

2. Click on the “Microsoft Azure App Service”

3. We choose our existing resource group name ( That we created ! “AzureDemo” ) in our Azure Portal and It will display the App Name inside the “AzureDemo” folder. This will display only when we are login through the Visual Studio using Azure credentials ( Email & Password).

Resource Name

Resource Name

OutPut

The application is hosted in given domain address  http://menoth.azurewebsites.net/

Reference

See Also

You can download other ASP.NET Core source codes from MSDN Code, using the link, mentioned below.

Summary

We learned how to create and deploy an ASP.NET Core web app in Azure. I hope this article is useful for all ASP.NET Core & Azure beginners.

 

Sending SMS using ASP.NET Core With Twilio SMS API


Introduction

In this article, we will explain how to Send SMS using ASP.NET Core With Twilio SMS API. Twilio provides third party SMS API for sending sms over the global network. So we can learn a little bit through this article.

Before reading this article, you must read the articles given below for ASP.NET Core knowledge.

Package Installation

  1. Install-Package Twilio -Version 5.9.1

This package will install all the sms,video,etc related classes,methods and API’s for twilio.

  1. Install-Package jQuery.Validation.Unobtrusive -Version 2.0.20710

This package will install all the bootstrap & validation related Jquery libraries in our project.

Important Notes

1. If you don’t have any twilio account then you should register a free account using the following link Click here & I choose language as “C#”.

2. Once registration is completed then we can access Dashboard and Console of our twilio account. We will get “Account SID & Auth Token Id” from Dashboard for sending sms.

Dashborad Console

Dashborad Console

3. We need a Twilio From number because that number has sent sms to the global network! So we need to enable Twilio SMS number ( This will send sms from ur “To” numbers ). Go to this link click here and Click on the “Get a number” button in the “Programmble SMS Menu” mentioned in the following screenshot.

Get a Number

Get a Number

4. You have to get $15 for sending sms In the twilio trial account. I can see in my account they are charging $1 + for each sms and after that you need to buy a paid plan.

Name Spaces

The following namespaces are providing “ASP.Net Core MVC” & “Twilio SMS API” Classes & Methods.

using System;
using Microsoft.AspNetCore.Mvc;
using RegistrationForm.ViewModels;
using Twilio;
using Twilio.Types;
using Twilio.Rest.Api.V2010.Account;

Configuring ASP.NET MVC in ASP.NET Core

We are going to add “UseMvc” Middleware and “AddMvc()” Configure Services in Startup.cs Class. The code given below clearly mentions that manually we need to add our controller name and an action name in “MapRoute”. We can change this controller name and action name, which is based on our requirement in the Applications.

 app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

Startup.cs

The class given below contains the complete middleware details in our Applications. I choose a default project in our Visual Studio 2015. So automatically it will generate the following classes & methods.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace SMSApp
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();

            if (env.IsDevelopment())
            {
                // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
                builder.AddApplicationInsightsSettings(developerMode: true);
            }
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddApplicationInsightsTelemetry(Configuration);

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseApplicationInsightsRequestTelemetry();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseApplicationInsightsExceptionTelemetry();

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Code
The following code help to send sms over the global network using ASP.Net Core With Twilio SMS API.

[HttpPost]
        public IActionResult Registration(RegistrationViewModel model)
        {
            ViewData["Message"] = "Your registration page!.";

            ViewBag.SuccessMessage = null;

            if (model.Email.Contains("menoth.com"))
            {
                ModelState.AddModelError("Email", "We don't support menoth Address !!");
            }

            if (ModelState.IsValid)
            {
                try
                {
                    // Find your Account Sid and Auth Token at twilio.com/user/account
                    const string accountSid = "AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
                    const string authToken = "6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
                    TwilioClient.Init(accountSid, authToken);

                    var to = new PhoneNumber("+91" + model.Mobile);
                    var message = MessageResource.Create(
                        to,
                        from: new PhoneNumber("+18XXXXXXXXXX"), //  From number, must be an SMS-enabled Twilio number ( This will send sms from ur "To" numbers ).
                        body:  $"Hello {model.Name} !! Welcome to Asp.Net Core With Twilio SMS API !!");

                    ModelState.Clear();
                    ViewBag.SuccessMessage = "Registered Successfully !!";
                }
                catch (Exception ex)
                {
                    Console.WriteLine($" Registration Failure : {ex.Message} ");
                }

            }

            return View();
        }

New Tag Helpers

We used latest ASP.NET Core Tag Helpers in Registration page to access controller and actions, validation etc.





<div asp-validation-summary="All" class="text-danger"></div>



<label asp-for="Name"></label>  
<input asp-for="Name" class="form-control" />  
<span asp-validation-for="Name" class="text-danger"></span>  
<a asp-controller="Home" asp-action="Home" class="btn btn-info">Cancel</a>

Inject Tag Helpers

In the way given below, we can inject the Tag Helpers in our Application. Now, create the default “_ViewImports.cshtml” file in View Folder and add the code given below in that file.

@addTagHelper "*,Microsoft.AspNetCore.Mvc.TagHelpers"

Client Side validations

The Client Side validation is done with the help of Bootstrap & jQuery etc.

Validation

Validation

Registration Page

The message will send to the respective mobile number that you have given in the mobile number column in registration page.

OutPut

We will get a sms from the Twilio account, once we have registered successfully.

Reference

Download

See Also

You can download other ASP.NET Core source codes from MSDN Code, using the link, mentioned below.

Summary

We learned how to Send SMS using ASP.NET Core With Twilio SMS API. I hope this article is useful for all ASP.NET Core beginners.

Startup Page In ASP.NET Core


Introduction

I think we all are familiar with the configuration of the default startup page in the previous versions of AP.NET but it’s slightly different in ASP.NET Core applications. In this article, I will explain how to configure the default startup page In ASP.NET Core.

Default Startup Page Configuration

There are two ways to implement the default startup page in ASP.NET Core.

  • Default Configuration
  • Customized Configuration

Before reading this article, you must read the articles given below for ASP.NET Core knowledge.

Default Configuration

We can use UseDefaultFiles() extension method in ASP.NET Core 1.0. UseDefaultFiles() will only search for the files given in “wwwroot”. If any of the files are detected first in “wwwroot”, the files are run as default in the client browser.

  • default.html
  • default.htm
  • index.html
  • index.htm

UseDefaultFiles must be called before UseStaticFiles or any other method (app.Run, app.Use) to serve the default file in the client-side browser. As you state UseStaticFiles() method after UseDefaultFiles(), it will run UseStaticFiles() method as a default and automatically terminates the other files which come after UseStaticFiles() method.

Customized Configuration

In this case, we are calling other customized pages as default startup pages in ASP.NET Core 1.0. Thus, we can use DefaultFilesOptions in ASP.NET Core 1.0. If you want to run other files as default, check the code given below in Startup.cs.

Full Code

The following code containsthe full source code of startup page configuration in ASP.NET Core.

using Microsoft.AspNetCore.Builder;  
using Microsoft.AspNetCore.Hosting;  
using Microsoft.AspNetCore.Http;  
using Microsoft.Extensions.DependencyInjection;  
using Microsoft.Extensions.Logging;  
   
namespace StartupConfig  
{  
    public class Startup  
    {  
        // This method gets called by the runtime. Use this method to add services to the container.  
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 Jump  
        public void ConfigureServices(IServiceCollection services)  
        {  
        }  
   
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)  
        {  
            loggerFactory.AddConsole();  
               
            DefaultFilesOptions DefaultFile = new DefaultFilesOptions();  
            DefaultFile.DefaultFileNames.Clear();  
            DefaultFile.DefaultFileNames.Add("Welcome.html");  
            app.UseDefaultFiles(DefaultFile);  
            app.UseStaticFiles();  
   
            if (env.IsDevelopment())  
            {  
                app.UseDeveloperExceptionPage();  
            }  
   
            app.Run(async (context) =>  
            {  
                await context.Response.WriteAsync("Hello World!");  
            });  
        }  
    }  
}  

project.json

The versions will be change based on the latest version’s updation in ASP.NET Core.

{  
  "dependencies": {  
    "Microsoft.NETCore.App": {  
      "version": "1.0.1",  
      "type": "platform"  
    },  
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",  
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",  
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",  
    "Microsoft.Extensions.Logging.Console": "1.0.0",  
    "Microsoft.AspNetCore.StaticFiles": "1.1.1"  
  },  
   
  "tools": {  
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"  
  },  
   
  "frameworks": {  
    "netcoreapp1.0": {  
      "imports": [  
        "dotnet5.6",  
        "portable-net45+win8"  
      ]  
    }  
  },  
   
  "buildOptions": {  
    "emitEntryPoint": true,  
    "preserveCompilationContext": true  
  },  
   
  "runtimeOptions": {  
    "configProperties": {  
      "System.GC.Server": true  
    }  
  },  
   
  "publishOptions": {  
    "include": [  
      "wwwroot",  
      "web.config"  
    ]  
  },  
   
  "scripts": {  
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]  
  }  
}  

Configuration Code

DefaultFilesOptions DefaultFile = new DefaultFilesOptions();
DefaultFile.DefaultFileNames.Clear();
DefaultFile.DefaultFileNames.Add("Welcome.html");
app.UseDefaultFiles(DefaultFile);
app.UseStaticFiles();

Reference

Output

Startup_Page

Startup_Page

See Also

You can download other ASP.NET Core source codes from MSDN Code, using the link, mentioned below.

Summary

We learned how to configure the default startup page in ASP.NET Core 1.0. I hope this article is useful for all ASP.NET Core 1.0 beginners.

Session State In ASP.NET Core and MVC Core


Introduction

In this article, we will explain how to create a “Session State in ASP.NET Core and MVC Core”.

Session State

In Session State, we can use to save and store user data while the user browses your web app. We already know that in previous versions of ASP.NET, we could store session as key value pair like this “Session[“Name”] = “Rajeesh Menoth”” and implement it in an easy way. But in the latest version of ASP.NET or ASP.NET Core, we need to do a few configurations for accessing and enabling Session State in the application. The main purpose of session is maintaining user data in memory because of HTTP is a stateless protocol.

Before reading this article, you must read the articles given below for ASP.NET Core knowledge.

Package Required

We need to install the stable version of “Microsoft.AspNetCore.Session” from Nuget Package Manager. Then only we can access Session State in ASP.NET Core 1.1.

Session In Nuget

Microsoft.AspNetCore.Session

.csproj

In “.csproj” we can check all the installed packages and versions details in ASP.NET Core 1.1.

<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Session" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
    <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />

Assemblies Required

These are the assemblies mainly required for accessing functionality of Session State, MVC, JSON, etc

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;

Home Controller

The following code is the example of sharing session in ASP.NET Core 1.1.

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;

namespace SessionInCore.Controllers
{
    public class HomeController : Controller
    {
        const string SessionKeyName = "_Name";
        const string SessionKeyAge = "_Age";
        const string SessionKeyDate = "_Date";

        public IActionResult Index()
        {
            HttpContext.Session.SetString(SessionKeyName, "Rajeesh Menoth");
            HttpContext.Session.SetInt32(SessionKeyAge, 28);
            // Requires you add the Set extension method mentioned in the SessionExtensions static class.
            HttpContext.Session.Set<DateTime>(SessionKeyDate, DateTime.Now);

            return View();
        }

        public IActionResult About()
        {
            ViewBag.Name = HttpContext.Session.GetString(SessionKeyName);
            ViewBag.Age = HttpContext.Session.GetInt32(SessionKeyAge);
            ViewBag.Date = HttpContext.Session.Get<DateTime>(SessionKeyDate);

            ViewData["Message"] = "Session State In Asp.Net Core 1.1";

            return View();
        }

        public IActionResult Contact()
        {
            ViewData["Message"] = "My Contact Details";

            return View();
        }

        public IActionResult Error()
        {
            return View();
        }
        
    }

    public static class SessionExtensions
    {
        public static void Set<T>(this ISession session, string key, T value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T Get<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) :
                                  JsonConvert.DeserializeObject<T>(value);
        }
    }
}

The following code contains the Key name as “SessionKeyName” & Value name as “Rajeesh Menoth”. So we can set the Session String “Key” and “Value” in SetString(“Key”,”Value”).

const string SessionKeyName = "_Name";
HttpContext.Session.SetString(SessionKeyName, "Rajeesh Menoth");

The following code contains a similar Session code as an older version of ASP.NET.

Session["Name"] = "Rajeesh Menoth";

We can Assign and Get the Session string value using “GetString(Name)” Method in a simple way.

ViewBag.Name = HttpContext.Session.GetString(SessionKeyName);

In the following way we can set and get serializable objects to Session in our application.

//Accessing Extension Method.
HttpContext.Session.Set<DateTime>(SessionKeyDate, DateTime.Now);
//Example of Extension Method.
 public static class SessionExtensions
    {
        public static void Set<T>(this ISession session, string key, T value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T Get<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) :
                                  JsonConvert.DeserializeObject<T>(value);
        }
    }

Configure Services

The first step is we need to add the Session services to the container. So we can add the services in “ConfigureServices” method in “Startup.cs” class in our application.

public void ConfigureServices(IServiceCollection services)
        {
            //In-Memory
            services.AddDistributedMemoryCache();
            services.AddSession(options => {
                options.IdleTimeout = TimeSpan.FromMinutes(1);
            });              
            // Add framework services.
            services.AddMvc();
        }

Configure the HTTP request pipeline

We add the “app.UseSession()” inside the Configure Method in “Startup.cs” Class because it gets called by the runtime. One more advantage is we can use this method to configure the HTTP request pipeline in our application.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseSession();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

OutPut – Active Session

Session Active

Session Active

OutPut – Session Expired

We set 1 mins as the Session Timeout in “ConfigureServices” method in Startup.cs class.

 services.AddSession(options => {
                options.IdleTimeout = TimeSpan.FromMinutes(1);//Session Timeout.
            });
Session Expire

Session Expire

Reference

See Also

You can download other ASP.NET Core source codes from MSDN Code, using the link, mentioned below.

Conclusion

We learned how to create Session State In ASP.NET Core and MVC Core. I hope you liked this article. Please share your valuable suggestions and feedback.

Building Applications with ASP.NET Core MVC 6 & Entity Framework Core using ASP.NET Core 1.0


Introduction

In this article, we will explain how to build the Applications with an ASP.NET Core MVC 6 & Entity Framework Core, using ASP.NET Core 1.0.

Before reading this article, you must read the articles given below for ASP.NET Core knowledge.

Model Class

We are going to create a registration page, using ASP.NET Core & EntityFrameWork Core. The Model class given below contains the properties of Registration details in our Applications.

using System;

namespace RegistrationForm.Models
{
    public class Registration
    {
        public Guid Id { get; set; }

        public string Name { get; set; }
        
        public string Location { get; set; }
        
        public string Mobile { get; set; }
        
        public string Email { get; set; }
        
        public string Address { get; set; }
    }
}

Dependency Required

The dependency given below is required to build ASP.NET Core MVC & EntityFrameWork Core Applications.

{
  "dependencies": {
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Mvc": "1.0.1",
    "Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.1",
    "Microsoft.AspNetCore.Mvc.ViewFeatures": "1.1.1",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.AspNetCore.StaticFiles": "1.1.0",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.EntityFrameworkCore.Design":"1.1.0",
    "Microsoft.NETCore.App": {
      "version": "1.0.1",
      "type": "platform"
    }  },

Tools Required

Add the Entity Framework Core tools in our Application.

"tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
    "Microsoft.EntityFrameworkCore.Tools": {
      "version": "1.0.0-preview2-final",
      "imports": [
        "portable-net45+win8+dnxcore50",
        "portable-net45+win8"
      ]
    }
  },

Configuring ASP.NET MVC in ASP.NET Core 1.0

We are going to add “UseMvc” Middleware and “AddMvc()” Configure Services in Startup.cs Class. The code given below clearly mentions that manually we need to add our controller name and an action name in “MapRoute”. We can change this controller name and action name, which is based on our requirement in the Applications.

app.UseMvc(config =>
           {
               config.MapRoute(
                   name: "Default",
                   template: "{controller}/{action}/{id?}",
                   defaults: new { controller = "Home", action = "Home" }
                   );
           });

LocalDB Configuration in ASP.NET Core 1.0

In the previous versions, everything is handled by Web.Config but in ASP.NET Core, the connection string is written in appsettings.json file. By default, it will show as a LocalDB path and as per our requirement, we can change the connection string path.

The appsetting JSON file contains the LocalDB connection string details in our Application and we have given the database name as “RegDB”. If you want to know more about JSON file configuration in ASP.NET Core, please check our previous article ADDING A CONFIGURATION SOURCE FILE IN ASP.NET CORE 1.0.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=RegDB;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

DbContext in ASP.NET Core 1.0

The code given below contains an information about EntityFrameWork Core DbContext. We can add the LocalDB connection string details with the help of “UseSqlServer” Method.

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace RegistrationForm.Models
{
    public class RegContext : DbContext
    {
        private IConfigurationRoot _config;

        public RegContext(IConfigurationRoot config, DbContextOptions options) : base(options)
        {
            _config = config;
        }
        public DbSet<Registration> Registrations { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer(_config["ConnectionStrings:DefaultConnection"]);
        }
    }
}

Seed Data in EntityFrameWork Core

We are going to implement Code First Migrations in an Entity Framework Core to seed the database with the test data and manually we are entering the seed data information in the “RegContextSeedData” class. The code given below contains the default values of Registration Details Table in our Application.

using System;
using System.Linq;
using System.Threading.Tasks;

namespace RegistrationForm.Models
{
    public class RegContextSeedData
    {
        private RegContext _context;

        public RegContextSeedData(RegContext context)
        {
            _context = context;
        }

        public async Task SeedData()
        {
            if(!_context.Registrations.Any())
            {
                var newReg = new Registration()
                {
                    Id = Guid.NewGuid(),
                    Name = "RajeeshMenoth",
                    Location = "Thuyyam",
                    Mobile = "123456789",
                    Email = "rajeeshmenoth@gmail.com",
                    Address = "Menoth Parambil House, Edappal Post, Thuyyam"
                };
                _context.Registrations.Add(newReg);
                await _context.SaveChangesAsync();
            }
        }
    }
}

Repository 

The code given below contains the common repository for our Application.

using System.Collections.Generic;
using System.Linq;

namespace RegistrationForm.Models
{
    public class RegRepository : IRegRepository
    {
        private RegContext _context;

        public RegRepository(RegContext context)
        {
            _context = context;
        }

        public IEnumerable<Registration> GetAllRegistrations()
        {
            return _context.Registrations.ToList();
        }
    }
}

Server Side Validation

In the View Model, we implemented the default validations in the Registration page in our Applications.

using System.ComponentModel.DataAnnotations;

namespace RegistrationForm.ViewModels
{
    public class RegistrationViewModel
    {
        [Required]
        public string Name { get; set; }

        [Required]
        public string Location { get; set; }

        [Required]
        [RegularExpression(@"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Not a valid Phone number")]
        public string Mobile { get; set; }

        [Required]
        [EmailAddress]
        public string Email { get; set; }

        [Required]
        [StringLength(5000, MinimumLength =10)]
        public string Address { get; set; }
        
    }
}

Controllers

In our Applications, we created two Controllers, where one is Home and another is Registration.

Home Controller

Home Controller returns all the registered user information list in home page with the help of common repository.

using Microsoft.AspNetCore.Mvc;
using RegistrationForm.Models;

namespace RegistrationForm.Controllers.WebApp
{
    public class HomeController : Controller
    {
        private IRegRepository _repository;

        public HomeController(IRegRepository repository)
        {
            _repository = repository;
        }

        public IActionResult Home()
        {
            var data = _repository.GetAllRegistrations();
            return View(data);
        }

    }
}

Registration Controller

The registration controller contains the registration information in our Application.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using RegistrationForm.Models;
using RegistrationForm.ViewModels;
using System;

namespace RegistrationForm.Controllers.WebApp
{
    public class RegistrationController : Controller
    {
        private RegContext _context;
        private ILogger<Registration> _logger;

        public RegistrationController(RegContext context, ILogger<Registration> logger)
        {
            _context = context;
            _logger = logger;
        }
        public IActionResult Registration()
        {
            return View();
        }
        public IActionResult Home()
        {
            return View();
        }
        [HttpPost]
        public IActionResult Registration(RegistrationViewModel model)
        {
            ViewBag.SuccessMessage = null;

            if (model.Email.Contains("menoth.com"))
            {
                ModelState.AddModelError("Email", "We don't support menoth Address !!");
            }

            if (ModelState.IsValid)
            {
                try
                {
                    Registration regData = new Registration()
                    {
                        Id = Guid.NewGuid(),
                        Name = model.Name,
                        Email = model.Email,
                        Location = model.Location,
                        Mobile = model.Mobile,
                        Address = model.Address
                    };

                    _context.Registrations.Add(regData);
                    _context.SaveChanges();

                    ModelState.Clear();
                    ViewBag.SuccessMessage = "Registered Successfully !!";
                }
                catch (Exception ex)
                {
                    _logger.LogError($" Registration Failure : {ex.Message} ");
                }
            }

            return View();
        }
    }
}

Startup.cs

The class given blow contains the complete middleware details in our Applications.

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RegistrationForm.Models;
using Microsoft.Extensions.Configuration;

namespace RegistrationForm
{
    public class Startup
    {
        private IConfigurationRoot _config;

        public Startup(IHostingEnvironment env)
        {
            var ConfigBuilder = new ConfigurationBuilder().SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json");
            _config = ConfigBuilder.Build();
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton(_config);
            services.AddDbContext<RegContext>();
            services.AddScoped<IRegRepository, RegRepository>();
            services.AddTransient<RegContextSeedData>();
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env,
            ILoggerFactory loggerFactory, RegContextSeedData seeder)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();

            app.UseMvc(config =>
           {
               config.MapRoute(
                   name: "Default",
                   template: "{controller}/{action}/{id?}",
                   defaults: new { controller = "Home", action = "Home" }
                   );
           });

            seeder.SeedData().Wait();

        }
    }
}

project.json

project.json contains the complete picture of dependency in our Applications.

{
  "dependencies": {
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Mvc": "1.0.1",
    "Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.1",
    "Microsoft.AspNetCore.Mvc.ViewFeatures": "1.1.1",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.AspNetCore.StaticFiles": "1.1.0",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.EntityFrameworkCore.Design":"1.1.0",
    "Microsoft.NETCore.App": {
      "version": "1.0.1",
      "type": "platform"
    }  },

  "tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
    "Microsoft.EntityFrameworkCore.Tools": {
      "version": "1.0.0-preview2-final",
      "imports": [
        "portable-net45+win8+dnxcore50",
        "portable-net45+win8"
      ]
    }
  },

  
  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "web.config"
    ]
  },

  "scripts": {
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

bower.json

The simple way in which we can say Bower is optimized for the front-end in our Applications and it provides the client side dependencies. For example, Bower manages the components and it contains HTML, CSS, JavaScript, fonts or even the image files.

{
	"name": "asp.net",
	"private": true,
  "dependencies": {
    "jquery": "~3.1.1",
    "jquery-validation": "~1.16.0",
    "jquery-validation-unobtrusive": "~3.2.6",
    "bootstrap": "~3.2.6"
    
  }
}

Code First Migration

First, we need to find the project location in CLI (Command Line Interface ) and afterwards, run the commands given below step by step.

  • “dotnet ef migrations add IntialDB” ( new EntityFrameWork migration ).
  • “dotnet ef database update” ( update the EntityFrameWork Core database in ASP.NET Core ).

To know more about it, please refer my previous article by Click here.

Project Structure

The structure given below will be created after the ef migration in ASP.NET Core.

Project Structure

Project Structure

New Tag Helpers

We used latest ASP.NET Core Tag Helpers in Registration page to access controller and actions, validation etc.

<div asp-validation-summary="All" class="text-danger"></div>

<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>

<a asp-controller="Home" asp-action="Home" class="btn btn-info">Cancel</a>

Inject Tag Helpers

In the way given below, we can inject the Tag Helpers in our Application. Now, create the default “_ViewImports.cshtml” file in View Folder and add the code given below in that file.

@addTagHelper "*,Microsoft.AspNetCore.Mvc.TagHelpers"

Client Side Validations

The Client Side validation is done through with the help of Bootstrap & jQuery etc. All these Client Side dependencies are accessed from bower.json file.

RegistrationForm Validation

RegistrationForm Validation

Output

Output

Reference

See Also

You can download other ASP.NET Core 1.0 source codes from MSDN Code, using the links, mentioned below.

Conclusion

We learnt how to build the Applications with ASP.NET Core MVC 6 & an Entity Framework Core, using ASP.NET Core 1.0. I hope, you liked this article. Please share your valuable suggestions and feedback.

Code First Migration : ASP.NET Core MVC 6 With EntityFrameWork Core


Introduction

In this article, we are going to explain Code First Migration in ASP.NET Core MVC 6 with EntityFrameWork Core, using Command Line Interface ( CLI ).

Before reading this article, you must read the articles given below for ASP.NET Core knowledge.

Model Class

We are going to create a sample Code First Migration project in ASP.NET Core 1.0. Model class given below contains the properties of the user details in our Applications.

using System;

namespace CodeFirstMigration.Models
{
    public class UserDetails
    {
        public Guid Id { get; set; }

        public string Name { get; set; }

        public string EmailId { get; set; }

        public string Company { get; set; }
    }
}

LocalDB Configuration in ASP.NET Core 1.0

In the previous versions, everything is handled by Web.Config but in ASP.NET Core, the connection string is written in appsettings.json file. By default, it will show as a LocalDB path and as per our requirement, we can change the connection string path.

In the way given below, we can create connection string in ASP.NET Core 1.0.

Appsetting in Asp.Net Core

Appsetting in Asp.Net Core

The appsetting JSON file contains the LocalDB connection string details in our Application and we have given the database name as “UserDb”. If you want to know more about JSON file configuration in ASP.NET Core, please check our previous article ADDING A CONFIGURATION SOURCE FILE IN ASP.NET CORE 1.0

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=UserDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

DbContext in ASP.NET Core 1.0

The code givden below contains the information about EntityFrameWork Core DbContext. We can add the LocalDB connection string details with the help of “UseSqlServer” Method.

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace CodeFirstMigration.Models
{
    public class CodeDbContext : DbContext
    {
        private IConfigurationRoot _config;

        public CodeDbContext(IConfigurationRoot config, DbContextOptions options) : base(options)
        {
            _config = config;
        }

        public DbSet<UserDetails> userDetails { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);

            optionsBuilder.UseSqlServer(_config["ConnectionStrings:DefaultConnection"]);
        }
    }
}

Seed Data in EntityFrameWork Core

We are going to implement Code First Migrations in Entity Framework Core to seed the database with test data and manually we are entering the seed data information in the “CodeDbSeedData” class. The code given below contains the default values of User Details Table in our Application.

using System;
using System.Linq;
using System.Threading.Tasks;

namespace CodeFirstMigration.Models
{
    public class CodeDbSeedData
    {
        private CodeDbContext _context;

        public CodeDbSeedData(CodeDbContext context)
        {
            _context = context;
        }

        public async Task SeedData()
        {
            if (!_context.userDetails.Any())
            {
                var user = new UserDetails()
                {
                    Id = Guid.NewGuid(),
                    Name = "RajeeshMenoth",
                    EmailId = "rajeeshmenoth@gmail.com",
                    Company = "HappiestMinds Technologies Pvt Ltd"
                };

                _context.userDetails.Add(user);
                await _context.SaveChangesAsync();
            }
        }
    }
}

project.json

project.json contain the complete picture of dependency in our Applications.

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.1",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.AspNetCore.Mvc.Core": "1.1.1",
    "Microsoft.EntityFrameworkCore": "1.1.0",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.1.0",
    "Microsoft.AspNetCore.Mvc": "1.1.0",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.1.0",
    "Microsoft.Extensions.Configuration.Json": "1.1.0",
    "Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final"
  },

  "tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
    "Microsoft.EntityFrameworkCore.Tools": {
      "version": "1.0.0-preview2-final",
      "imports": [
        "portable-net45+win8+dnxcore50",
        "portable-net45+win8"
      ]
    }
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "web.config"
    ]
  },

  "scripts": {
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

Startup.cs

The class given blow contains the complete middleware details in our Applications.

using CodeFirstMigration.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;

namespace CodeFirstMigration
{
    public class Startup
    {
        private IConfigurationRoot _config;

        public Startup(IHostingEnvironment env)
        {
            var ConfigBuilder = new ConfigurationBuilder().SetBasePath(env.ContentRootPath)
                        .AddJsonFile("appsettings.json");
            _config = ConfigBuilder.Build();
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton(_config);
            services.AddDbContext<CodeDbContext>();
            services.AddTransient<CodeDbSeedData>();
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory,
            CodeDbSeedData seeder)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync(" Welcome to Dotnet Core !!");
            });

            try
            {
                seeder.SeedData().Wait();
            }
            catch (Exception ex)
            {

                throw ex;
            }
           


        }
    }
}

Code First Migration

The steps given below will explain the step by step Code First Migration in EntityFrameWork Core.

Setting Project Location

The command given below will help to change our current “C Drive” to “F Drive” because currently our Code First Migration project is saved into “F Drive”.

Drive Changing

Drive Changing

Dotnet Help Command

The command given below will display for more information about dotnet ef command.

“dotnet ef –help”

Dotnet EF Commands

Dotnet EF Commands

Starting With New Migration

We are going to start with new EntityFrameWork migration, using the command given below.

“dotnet ef migrations add IntialDB”

EF New Migration

EF New Migration

Update the database

The command given below will update the EntityFrameWork Core database in ASP.NET Core Application.

EF Update the Database

EF Update the Database

Project Structure After Migration

The structure given below will be created after the ef migration in .NET Core.

Migration Structure

Migration Structure

Local Db Created

The Dotnet EntityFrameWork CLI ( Command Line Interface ) creates the Local DB as “UserDB”. Go to “View” and select “SQL Server Object Explorer” in Visual Studio. Now, expand “SQL Server -> (localdb) -> Databases -> UserDB”.

LocalDb Created

LocalDb Created

Output

Output

Output

Download Source Code : Code First Migration

Conclusion

We learned about Code First Migration in ASP.NET Core MVC 6 with EntityFrameWork Core, using Command Line Interface ( CLI ) and I hope you liked this article. Please share your valuable suggestions and feedback.

Reference

See Also

You can download other ASP.NET Core 1.0 source codes from MSDN Code, using the links, mentioned below.

%d bloggers like this: