Creating your ASP.NET MVC 5 Application from SCRATCH for Beginners: Using Entity Framework 6 and Identity with CRUD Functionalities

Interested in creating your own website? Want to learn a new Ever wondered how cool is it to have a website that has a log-in/log-out functionality? Want to learn how to Create, Read, Update or Delete(CRUD) records in a database? Are you lost track on your tutorials?  Well, I’m going to teach you how to create one from scratch where in you will know every single details on how the code works. If you are new to back-end web development, this tutorial is for you. I’ll explain everything in detail so that you won’t have to research some particular methods being used. Also I won’t be focusing on the websites design since were after the functionalities. What will be doing is a simple item list when the users is logged in. 

If ever you are an experienced programmer with a little background on C#  and stumbled upon online tutorials, most likely you are referred to just creating the built-in internet application template of Visual Studio which is very complicating to understand. Be it the MVC, Web API, Single Page, etc, Visual Studio has it made as a template. Not really beginner-friendly if you ask me. So I made this article for beginners, explained everything and built from scratch. Hopefully after this, you could try to build your own site using ASP.NET MVC.

 Pre-requisites

In this tutorial, we’ll be using the following software’s together with some programming languages. If you have zero knowledge on the following especially on Object-Oriented Programming (OOP), you will definitely have a hard time understanding this as this article uses a lot of OOP concepts. If you want to have a little refresher, this article is a good start. Moving on to the pre-requisites:

  1.  Object-Oriented Programming Knowledge – Just reiterating what I said earlier and just to clarify a little further, its preferred that you know this. Although I’m not saying this is totally mandatory, its better to have a little background in order to easily grasp the topic. Know at least the basics. Don’t worry, you don’t have to master everything as long as you know how an object works.
  2. C# Programming LanguageThis will be our back-end code and pretty much the majority of what we’re writing.
  3. HTML/CSS – Pretty much the bread and butter of web applications but still worth mentioning for starters.
  4. Internet connection – I know it may sound a little obvious but its still worth mentioning. This is very minimal and you don’t need this the entire tutorial. Placed it to give you an idea to prepare for a few seconds of stable connection. Reason is we’ll be getting libraries on NuGet which requires an internet connection.
  5. SQL – A little bit about databases will do. If you have knowledge on object-relational databases then you can easily grasp the topic.

For the software, you’ll be needing the following:

1.) Visual Studio Ultimate 2013  OR Visual Studio 2013 Community OR Visual Studio 2012Our Software and IDE for developing our app. For ultimate, better if you can download together with update 4.You may start with a 90-day free trial. If you still have VS2012 you can still use it however by default it might not provide you with MVC 5 so you’ll need to adjust and update it to have it support MVC 5. If your school is subscribed to a Dreamspark premium or your company owns a Bizpark license, you may get it there provided with a corresponding serial key. VS2013 Community is free in any case your license has expired on Ultimate or if you didn’t availed one.

Warning: The file is approximately 5GB so make sure to have a good internet connection regardless if you got the ISO or the small EXE installer. Installation might take more or less 3 hours depending on your PC specs and even on some cases an ENTIRE DAY  (which happened to me) so make sure you do this in advance before starting.

2.) Internet browser – IE, Chrome, Safari, Opera, whatever suites you. This will be used to view your web page.

Make sure to have Visual Studio 2013 installed. If ever you have Visual Studio 2012, it has a different file structure so you might get confused nor get lost along the tutorials so it is recommended that you use VS2013.

Table of Contents

I’m not going to subdivide this into separate articles as it can seem confusing. I’ll place the processes here so that in case you want to resume, you can simply press control + f OR command + f then look for the number where you last stopped.

  1. Creating your Empty Project
  2. Creating the Authentication Middleware using Identity
    1. Installing the Owin packages
    2. Coding the Middleware
    3. Connecting the Middleware to the Solution
  3. Creating the Basic Home Pages
    1. Adding the Home Controller
    2. Adding the Home View
    3. Explaining Views and Master Page
  4. Adding Authentication Security and Unauthorized Page Placeholder
  5. Creating the Login Model and Login Form
  6. Adding the Login logic With Hard-coded Values
    1. Adding the HttpGet Login Method
    2. Adding the HttpPost Login Method
    3. Adding Credential Validations
    4. Displaying the Error Message and Adding URL Validation
  7. Displaying Persisted Values and Adding the Logout Logic
    1. Displaying Your Name
    2. Creating the Logout Button and Logic
  8. Creating the Database using LocalDb
    1. Connecting the Database to the App through Connection Strings
    2. Creating the Database Tables
  9. Linking the Database Through Entity Framework
    1. Creating the Context and Renaming the LoginModel
    2. Cleaning our AuthController Redirection
  10. Creating the Registration Page
    1. Creating the Registration Action and View Page
    2. Creating Data Encryption and Decryption
    3. Creating the Query Logic
    4. Editing the Login Logic
  11. Creating our List Table
    1. Creating the UI for the tables
    2. Creating the List Model and Linking it to the Database
    3. Adding Input Fields
    4. Explaining Relationships Between Tables: Another Logged-in User = Different Item List
  12. Adding Items to our List
  13. Displaying the Items to the List
  14. Editing the Items
    1. Adding the Edit View
    2. Creating the Edit Logic
  15. Deleting Items from the List
  16. Displaying Public Data
  17. Cleaning the Code
  18. Debriefing and Summary

Note before starting: In case the picture is tool small or unreadable, you can click the picture for the enlarged version. In case you get lost, I have the complete copy of the code which you can use for a reference at the end of the tutorial (At chapter 18).

1.) Creating your Empty Project

Let’s first create a new project. Open your Visual Studio (In my case, I’m using Visual Studio Ultimate 2013) and go to New Project (located on the left side) then a pop-up window will appear. From there go to Installed > Templates > Visual C# > ASP.NET Web ApplicationFrom the name textbox (located below), name the project MyFirstWebsite then click OK.

1

Next on the next window, select Empty on the template window and click on the MVC checkbox below on the Add folders and core references for: then click OK.

2-2

 

 Now you might ask what’s with the MVC reference? It means when we create the project, we’re adding the following folders:

  • App_Data
  • App_Start
  • Controllers
  • Models
  • Views

And that’s it. It only creates 5 folders. Don’t worry, they are pretty much empty folders (except for App_Start and Views. I’ll explain the one file residing inside them later) and we’re still building the app from scratch. The only difference from this on not checking the MVC checkbox is that in a literally empty project, those folders are not created. Your workspace should look like this:

3

Enclosed in the box are the folders created from the MVC reference as I mentioned earlier. Then again if not checked, just imagine those folders are gone (which means the solution file, Properties, References, Global.asax, packages.config and Web.config is only present in a literally empty project)

 

Now you might notice that inside the App_Start folder, there’s a RouteConfig.cs and inside the Views folder is a web.config file. These are initially created on the MVC reference. RouteConfig.cs is the file that deals with the how URL routings of your app work. We’re not going to do anything with it as we are not customizing our own routes yet. Now you might notice we have a web.config inside the Views folder and one outside. Don’t get the two confused!

 The one inside the Views folder is used to tell the project that within the Views folder, we can use Razor syntax within our cshtml file (our views or rather, our html file designed to accept OOP razor codes).

The one outside is used to configure the entire project’s references and connections.

10

2.) Creating the Authentication Middleware using Identity

Next, we’ll create our middleware using ASP.NET’s identity. You might ask what a middleware is. In a nutshell, a middleware is the pipeline between the communication of the server and the application. For short, its a bridge between the two. You can read more on this great article. On the Solution Explorer located on the right, right-click on App_Start. Go to Add > Class…

4

From the class, we’ll name it Startup.cs then click OK

5

Startup.cs in the standard internet application template is the default name and middleware  where we place settings from cookies. In our case, we’ll build it from scratch.

 

2.1 – Installing the Owin Packages

From the Solution Explorer, right-click on MyFirstWebsite then click on Manage NuGet Packages…

6

On the search bar on the upper-right, type in Microsoft.Owin.Host.SystemWeb then click on Install beside it then just agree on the terms and continue. Wait for the installation to finish. We are installing Owin,  .NET’s middleware specifiation.

 Note: You’ll need an internet connection to get the library

7

 

After, you should see a green check-mark beside it indicating that its successfully installed. This time, type on the search bar Microsoft.Owin.Security.Cookies then install.

8

A green check-mark should appear beside it. Now we’re set to code our middleware. On Startup.cs, add the owin libraries by placing this on top. This is the libraries we downloaded earlier and now we’re placing it as a reference.

using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
 

Then the following function inside the Startup class:

public void Configuration (IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = "ApplicationCookie",
        LoginPath = new PathString("/auth/login")
    });
}
 

2.2) Coding the middleware

9

Here’s the explanation to the code:

  • IAppBuilder Parameter object that serves as the entry point to the pipeline. This serves as the linking of pipeline branches
  • app.UseCookieAuthentication – From the method itself, we’re going to use cookie-based authentication. Have no idea what cookie-based authentication means? This Stackoverflow answer pretty much explains it. In a nutshell, it means you provide a word and set its value in which this word will be used to bridge the communication of the app and server.
  • CookieAuthenticationOptions – This class contains the options that will be used for cookie-based authentication. Note that this is a parameter inside the UseCookieAuthentication method.
  • AuthenticationType – This is a property defined within the CookieAuthenticationOptions class. We say that we’re using an “ApplicationCookie” which is a string that defines the cookie.
  • LoginPath – Its assigned from PathString Object in which the URL it contains is where the user will be redirected if he/she is not authorized.

2.3) Connecting the Middleware to the Solution

Now that we have our middleware created, lets let our project know that we created one and have it executed at the start of the app. Open the Web.config file from the solution and inside the <appSettings> tag on top, add the following line:

&amp;lt;add key="owin:AppStartup" value="MyFirstWebsite.App_Start.Startup"/&amp;gt;

11

Let me explain the tag format. the key indicates that you have owin to start on the execution of the app. value indicates the namespace of your Startup.cs file in our case, its MyFirstWebsite.App_Start and lastly the class name which is Startup. Connecting the dots, we have the value MyFirstWebsite.App_Start.Startup

If you don’t know where the namespace comes, its the directory from your solution. This will show you how to locate the namespace of the class:

12

HOLD YOUR HORSES! DO NOT RUN THE APP YET! 

If you do, it will throw you an error saying you have no default page. Now that’s the next thing we’re going to do.

 

3.) Creating the Basic Home Pages

Now let’s create our basic placeholder page. With that, we’ll create a MVC controller named “Home“.

3.1) Adding the Home Controller

From the Solution Explorer, right-click the Controller folder then Add > Controller…

13

From the controller window, select MVC 5 Controller – Empty then click on Add

14

Another window will appear. Name it as HomeController and click on Add. It should now scaffold and after, you should have something like this:

15

 

If you are wondering what’s this Controller term, its the C from the acronym MVC. MVC stands for Model-View-Controller. We’ll not dig deep into it but in a nutshell, what the controller does is we process all the logic here. Model is basically the data. Just imagine it as database tables. View is the look and feel of your app.

 

3.2) Adding the Home View

Next, we’ll create the view for our home controller. This is the so-called HTML of the controller. Right-click on the Index() method then click on Add View…

16

A window for the view settings appear. Leave the View name as Index and leave everything as is then click Add.

17

 

It will then create Index.cshtml inside the Views > HomeNow let’s try running the app by clicking the given browser on top with an arrow beside it (Below the DEBUG, TEAM and TOOLS navigation and currently above the Startup.cs tab. Refer to the squared area above). In my case, I’m using Google Chrome.

18

 

It should have a layout like this:

19

WHOAAAAH WAIT! I know you might be expecting a plain HTML page but all of a sudden, why was there a black nav bar and a footer? That’s the next portion I’ll discuss. By the way, you might notice the URL route is Home/Index. By default, Home controller is default controller and Index is the default action method that the site finds whenever running. You can check the RouteConfig.cs file located on the App_Start folder (Refer to the second image below).

 

By the way, you can stop the program from this point. To stop the program, there should be a square button on the right.

34

 

RouteConfig.cs:

22

 

Next you might ask “How do I run the web app without the Home/Index appearing? How do I set it as locahost:<portnumber> without the URL as my default page?“. Simple. Make your URL property as an empty string or in other words, url:””. Your default View is still from Home controller and Index action method but the URL should now appear only as localhost.

I’m not going to do that as I’ll just go with the flow for now. I just gave you an idea just in case you want to modify the app for future use.

3.3) Explaining Views and Master page

Have you recalled the part where you created your Home view index? There was a portion there that says “Leave empty if it is set in a Razor _viewstart file“. _ViewStart file is located at the Views folder and I’ll be explaining it in a bit while.  Let me show to you that window again and look at the lowest text box (This was also the picture from part 3.2):

17

 

You have the “Use a layout page:” checked by default so it will reference a master page. The master page by default is named as _Layout.cshtml and located at Views > Shared. How was that configured by default you ask? Its at the _ViewStart.cshtml file. It tells where’s the default master page should be located whenever you check and leave the directory empty. If you’ll open it, it should have the code like this:

@{
 Layout = "~/Views/Shared/_Layout.cshtml";
}

telling that the default master page is always located on that directory and will always be the default, not unless changed.

A master page is a page to be used all throughout so that you don’t need to re-code again similar HTML tags such as navigational bars and footers. This makes structuring cleaner to read. Let’s open our _Layout.cshtml and see what it looks like:

20

 

 

Get it now? You notice that there’s a @RenderBody() method. It renders the view from your action method. In every master/partial page, @RenderBody is always required. Regarding the CSS classes, they are predefined on the Bootstrap framework. The bootstrap file was also generated when the project was created. Its a framework created for mobile-friendly websites. we’ll not dig deep into it but if you like to learn on how to code bootstrap, this is a great start.

Note that this framework is not created by Microsoft so don’t get confused about it. It was generated during project creation but doesn’t mean they own it. its open source so its free to be modified.

 

Moving on, you might question how did Startup.cs get in the picture? The thing is it’s not yet there and that’s our next job.

 

4.) Adding Authentication Security and Unauthorized Page Placeholder

On the Solution Explorer, right click on App_Start folder then add another class named “FilterConfig.cs“. From there, add the using System.Web.Mvc as your reference and the following code:

 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
     filters.Add(new HandleErrorAttribute());
     filters.Add(new AuthorizeAttribute());
 }

21

 

We created a function named RegisterGlobalFilters with a parameter called GlobalFilterCollection. What does that mean? GlobalFilterCollection is a class that deals with filtering. They define action methods that usually have a one-to-one relationship with possible user interactions, such as clicking a link or submitting a form. Filters are custom classes that provide both a declarative and programmatic means to add pre-action and post-action behavior to controller action methods.  For example, when the user clicks a link, a request is routed to the designated controller, and the corresponding action method is called. You can read this for more info.

Inside the method we’ve added 2 class named HandleErrorAttribute and AuthorizeAttributeHandleErrorAttribute is the class that will handle all exceptions thrown by the action methodAuthorizeAttribute on the other hand is the main reason why we created the filter. What that class does is to specifies access to a controller or action method that is restricted to users who meet the authorization requirement.

 

Lastly, we’ll let the app know that FilterConfig.cs exists and it should always start during run-time of the app. On your solution explorer, go to Globax.asax.cs and add its reference (the files namespace) using MyFirstWebsite.App_Start on the top. Next, add FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters) below RouteConfig.

23

Now that we have our filters, lets try and run the app. It should appear like this:

24

 

WOAAAAAHH CALM DOWN! I know an error occurred but its fine and it means you’re on the right track! 

It will definitely produce an error due to the following reasons:

  1. We are not authorized even on our default route, which is Home/Index – You are always directed to that page. TRUE! Then again its your default page. You might asked how was that route secured? Have you recalled the filters you placed earlier? AuthorizeAttribute in particular? Yup that’s right! That’s the reason why. Every controller you have is considered to be part of an authorized page. Thats the purpose of the AuthorizeAttribute. The app is trying to look for cookies for authentication but it doesn’t exist. Its linked with Startup.cs as it tells our application uses Cookie authentication. Try removing filters.Add(new AuthorizeAttribute()); and run the app. It should work so you can see but make sure to bring the code back.
  2. We don’t have a placeholder page yet for the route auth/login – If you recall error 404, it means page is not found. If you also recall our RouteConfig, format goes as {controller}/{action} in our case, we have not created the AuthController and an action method called login. The ?ReturnUrl=%2F  is just a query string which appear whenever you are redirected. %2F means a forward slash (/) where in 2F is the hexadecimal value for a forward slash and the percent sign (%) tells that its an ASCII character. You might ask why auth/login is ourdefault redirected page(route) for unauthorized users. Have you recalled your Startup.cs? Your LoginPath string? Putting this picture again might do the trick:

9

Having those said, lets resolve the error by creating a controller (empty MVC 5) named AuthController and replace the Index() action method to Login().

Note that you will see a red line once you rename it. Put your cursor there and a drop-down will appear. Rename it to Login. The reason for that is to rename everything referenced from that action to the newly edited action name.

25

 

Now let’s create our Login view by right-clicking the Login() then Add View… Leave everything as is then Add. You should have an Auth folder within the Views folder then the view should look like this:

26

 

Let’s run the program once again and see what happens…

27

 

WOAAAH RELAAAX! Then again, its fine and if this happens, you are on the right track!

 

You might scratch your head on this. You already created a controller, an action method, and a placeholder page that represents auth/login but yet an error still occurs. If you recall the two reasons I’ve said earlier, we only solved problem number 2 BUT not yet problem number 1. Let me just say it again, because of AuthorizeAttributeEvery controller your have is considered to be part of an authorized page. Meaning, your auth/login is considered to be a secured authorized page which is also one of the reasons why you have a looping redirects and those looping causes you to stack up the query string on the URL (which is auth/login?ReturnUrl=%2).

Let’s solve that problem shall we? On your AuthController, place in the Data Annotation on top of the class [AllowAnonymous]

28

It simply says that everything under your AuthController can be accessed by anyone. This also by-passes the AuthorizeAttribute filter telling it that it shouldn’t be a always a page for authorized users.

Now let’s run again the app and see what happens…

29

 

Phew! We finally have it working!

We have finally finished securing the Home Page. Next stop, creating our Model and form for logging-in.

5.) Creating the Login Model and Login Form

If you don’t know what Model is, just so you know its the representation of your database entities. In other words, its what you ask or let the user input for information (such as textboxs and checkboxes).

We’ll create one by making a class. On your Models folder, create a class and name it LoginModel.cs

30

Then in your class, add using System.Web.Mvc and using System.ComponentModel.DataAnnotations as your references and the following code inside the class:


[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[HiddenInput(DisplayValue=false)]]
public string ReturnUrl { get; set; }

31

 

Those are the representations of our login form later. Annotations such as [Required] tell those model entities are associated to it whereareas:

  • [Required] – required input field. If stated and if this portion is left null, then the form will not submit.
  • [DataType(DataType.Password)] – Tell that this field is a password. So the textfield should be masked with dots just as a typical password field.
  • [HiddenInput(DisplayValue = false)] – A hidden input text field. This can be considered as a temporary storage of data.

Next let’s create our login form. On our Login view, let’s place the following code:


@model MyFirstWebsite.Models.LoginModel
@{
    ViewBag.Title = "Login";
}

&amp;lt;h2&amp;gt;Log In&amp;lt;/h2&amp;gt;

@Html.ValidationSummary(true)

@using (Html.BeginForm())
{
    @Html.EditorForModel()
    &amp;lt;p&amp;gt;
       &amp;lt;button type="submit"&amp;gt;Log In&amp;lt;/button&amp;gt;
    &amp;lt;/p&amp;gt;
}

32

Here’s the explanation to the code:

  • @model MyFirstWebsite.Models.LoginModel – Loads the reference for the Login model to let the view know we’re using a model
  • @Html.ValidationSummary(true) – This reveals the output message if ever a validation error occurs. For instance, if you submitted texts in a numbered-only text box or did not place any values on a required field would result this area to display the errors. The true argument states that it should only display mode-related errors, otherwise if false, it will display every error. We place true because we’d only care on model-related errors for now.
  • @using (Html.BeginForm()) {}– This is equivalent to a <form> tag.
  • @Html.EditorForModel() – Displays your model based on the attributes. Pretty much lays all the cards in the table regarding your model.
  • I guess I don’t need to explain the following HTML tags below…

Run the app and it should look like this:

33

 

As you can see, the form was automatically created based on your model. Next, we’ll create our logic for Login and Logout using hard-coded values.

 

6.) Adding the Login with hard-coded values

We’ll put into action one of the main features of our app which is having a Login and Logout feature.

6.1) Adding the HttpGet Login Method

We’ll update your AuthController and type in the following code:


[HttpGet]
public ActionResult Login(string returnUrl)
{
    var model = new LoginModel
    {
        ReturnUrl = returnUrl
    };
}

 

35

Note: If you are having an error on instantiating the LoginModel, just right-click it (As in the LoginModel word itself) > Resolve > using MyFirstWebsite.Models. That should do the trick and unfortunately, I didn’t placed it in the reference on the screenshot 🙁

 

We’ve added a data annotation named [HttpGet] and added a parameter named string Url. HttpGet basically gets the value of your URL query string. If you recall it, our query string is ReturnUrl and its value is %2F. The string parameter returnUrl gets the first value of the query string (which is %2F). The value being passed is now a forward slash (/) since its not anymore encoded in the URL. 

Next we declared the Login model object passing it to model variable and inside, we assigned the model’s ReturnUrl from the returnUrl parameter. We’ll let our model know this value. Then lastly we return the value of the model object to our view. If you recall our view, we declared a namespace @model MyFirstWebsite.Models.LoginModel. This lets us know we have a model and in our case, we only passed in ReturnUrl and the rest of the values (email and password) are null. So in our view, if we did something like @Model.ReturnUrl, it will display the backslash (It shouldn’t since its a hidden input). 

Try typing in @Model.ReturnUrl in your Login view and remove the annotation [HiddenInput(DisplayValue = false)]. It should display the backslash but it should appear in a textbox as by default, EditorForModel() converts strings as a textbox editor.

Make sure to bring the code back once you’re done testing it.

 

 6.2) Adding the HttpPost Login Method

Next we’ll create another method that’s the same as Login but the difference is for the purpose of a HttpPost. Write this below your first Login method:


 [HttpPost]
 public ActionResult Login(LoginModel model)
 {
&amp;nbsp; &amp;nbsp; return View(model);
 }

36

This doesn’t do any logic yet  but the purpose is just to create a placeholder method to have it prepared. This returns the model value coming from the input fields. Then again, they are represented by LoginModel so values are passed to that object. The thing that triggers the HttpPost is through clicking the submit button. The app already knows that a POST request will be submitted whet you have a submit button. Now let’s put it into action and test whether clicking the submit button will get the value. In your Auth view, type in Model.Email and Model.Password having a <H1> tag.

37

 

Run the app and type in the email address “admin@admin.com” and password “123456” then click on submit. It should look like this, displaying your input:

38

Now that we know how to pass and display values, lets move on to adding credential validations but first, remove <h1>@Model.Email</h1> and <h1>@Model.Password</h1> as you don’t need it anymore. We only demonstrated how it works.

6.3) Adding the Credential Validation

As a developer, the first thing that comes into your mind when you hear the word “validation” is an if-else statement. Off course we need to compare whether the inputs are right or wrong. We’ll create one inside our HttpPost Login Method. Add in the library using System.Security.Claims as we’ll be using claims as our security.

39

In your Post Login Method, type in the following:

public ActionResult LogIn(LogInModel model)
{
    if (!ModelState.IsValid) //Checks if input fields have the correct format
    {
        return View(model); //Returns the view with the input values so that the user doesn't have to retype again
    }

    //Checks whether the input is the same as those literals. Note: Never ever do this! This is just to demo the validation while we're not yet doing any database interaction
    if (model.Email == "admin@admin.com" &amp;amp;&amp;amp; model.Password == "123456")
    {
&amp;nbsp; &amp;nbsp;     var identity = new ClaimsIdentity(&amp;nbsp;new[] {
&amp;nbsp; &amp;nbsp;     new Claim(ClaimTypes.Name, "Xtian"),
&amp;nbsp;     &amp;nbsp; new Claim(ClaimTypes.Email, "xtian@email.com"),
&amp;nbsp;     &amp;nbsp; new Claim(ClaimTypes.Country, "Philippines")
    }, "ApplicationCookie");

    var ctx = Request.GetOwinContext();
    var authManager = ctx.Authentication;
    authManager.SignIn(identity);

    return Redirect(GetRedirectUrl(model.ReturnUrl));
    }

    return View(model); //Should always be declared on the end of an action method
}

40-1

Yup there is an error stating that we have no GetRedirectUrl. We have not created that method yet so relax. We’ll do that later so don’t run the app yet. Now you might get agitated on the code. I know what’s inside the if statement can be very confusing but I’ll be explaining them one by one:

  • var identity = new ClaimsIdentity( List of new Claims(), string Authentication Type) – This part seems too long but to explain, we assigned the ClaimsIdentity object into a variable called identity. The first parameter is new Claims(). As mentioned there, you can place a list of claims. It is declared as an array object as defined from new [] { }. The last parameter should be what type of authentication. in our case its ApplicationCookie.
  • new Claim(Claim type, string claim value) – This is the specific type of claim inside the list. In claims, you declare one the first parameter what type of claims you want to have. This will be used as our cookies throughout our app. In our case, we used name, email and country. Click here for the complete list of claim types you can use.

The following is now outside the if-statement of the validation:

  • var ctx = Request.GetOwinContext() Here, we are passing the value to a variable called ctx. the Request object is a keyword that reads HTTP request values sent by the client. GetOwinContext() is a method that tells that we have to get the OWIN context in which links our middle ware to the request. This return null if a middleware doesn’t exist.
  • var authManager = ctx.Authentication – Next, we declare a variable named authManager and assign it a value. ctx came from the variable we declared earlier. Authentication is an object property coming from GetOwinContext() that links our middleware to an authentication to the app. For short, the 2 variables can be combined as Request.GetOwinContext().Authentication but distributing it makes it cleaner to read.
  • authManager.SignIn(identity)authManager was that variable we declared earlier. SignIn is a method that gets the list of claims and uses to authenticate those values to be persisted throughout the app. The list of claims is the first parameter which was assigned to the variable identity which we declared earlier inside the if-statement.
  • return Redirect(string URL where you will be redirected) – Simply redirects you to the URL placed inside the method.

6.4) Displaying the Error Message and Adding URL Validation

Lastly, lets place our error message right before returning the view in case we don’t get redirected by adding in ModelState.AddModelError(“”, “Invalid email or password”);

41

Now that we’ve explained them, lets create our GetRedirectUrl method to finish the job. We’ll be using this to validate our URL in case we placed the credentials correctly. Type the following code below the Login method:


private string GetRedirectUrl(string returnUrl)
{
    if (string.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl))
    {
        return Url.Action("index", "home");
    }
    return returnUrl;
}

42

 

What we’re doing is we are validating if the string is empty or not, if not then it will direct us to Home/Index route (rather our Home controller and Index Action). Run the app and with an email “admin@admin.com” and with the password “123456“. You should now be redirected to this page:

 

43

You’ve noticed that the browser asks if you want to save your password. That’s because it received a post request and cookies we’re saved to the browser.

 

We’re now on an authenticated page, let’s display the persisted values together with the logout. Stop the application from this point.

7.) Displaying Persisted Values and Adding the Logout Logic

Let’s modify our page and display a name and a logout tab.

7.1) Displaying Your Name

On our _Layout.cshtml master page, let’s edit the Application Name into your name by replacing the the “Application Name” into @User.Identity.Name and a simple if-statement to display something when not logged-in. Type in the following in that portion:


@if(@User.Identity.IsAuthenticated)
{
     @Html.ActionLink("Hello " + @User.Identity.Name + "!", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
}
else
{
     @Html.ActionLink("Login", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
}

 

44

Run the app again and see how it looks like:

45

 

Even though we stopped the app and run it again, the session still exists. It’s because the cookies still exists within the browser. The name was based from the Claims value we assigned earlier. Next, let’s create our Logout button.

7.1) Displaying the Logout Button and Logic

From the _Layout.cshtml, add the following code within the navbar tag:


&amp;lt;div class="navbar-collapse collapse"&amp;gt;
    &amp;lt;ul class="nav navbar-nav navbar-right"&amp;gt;
        &amp;lt;li&amp;gt;
            &amp;lt;a href="@Url.Action("Logout", "Auth")"&amp;gt;Logout&amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;

 46

 

The Action parameters are (action method, controller) wherein if we click it, we’ll go to Logout action method and Auth controller. From our AuthController, lets add our Logout method:


public ActionResult Logout()
{
    var ctx = Request.GetOwinContext();
    var authManager = ctx.Authentication;

    authManager.SignOut("ApplicationCookie");
    return RedirectToAction("Login", "Auth");
}

47

 

It is set to be redirected to Auth/Login page when logged out. Lets run the app again. Login and as you can see, you have the logout on the upper-right portion on the navbar.

 

48

 

Click on Logout and it should redirect you back to the Login form.

Tadaaaa! We’re done with our Authentication and security. Next topic, we’ll be dealing with data dynamically wherein we will use a database to store and display data. We will modify the code we did. what we’ll be doing is a list app when the user is logged in.

 

8.) Creating the Database using LocalDb

We’ll be using the lightweight LocalDb to keep things simple. Although in .NET apps, its common to connect through MS SQL Server and manipulate the databases from there but we’ll be using the built in LocalDb to keep things simple and straightforward.

From you Solution Explorer, right-click the App_Data folder then Add > SQL Server Database…

49

 

A window will appear, name your database as MyDatabase and it should appear like this:

50

*Issuance Checkpoint*

In case you’ve been going through errors in creating the database, we’ll debug it here and I’ll state some possible solutions but if you we’re able to create the database flawlessly, you can skip this part.

1.) If you cannot create a SQL Server Local Database, I download the 2012(ver. 11) here or 2014(ver. 12) here (pick LocalDB 32BIT\SqlLocalDB.msi for 32bit or LocalDB 32BIT\SqlLocalDB.msi for 64bit).

2.) If you encountered this error after you’re done entering the Database name:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 50 – Local Database Runtime error occurred. Cannot create an automatic instance. See the Windows Application event log for error details

It means you need to manually create and start your LocalDb instance. To do that, you’ll first need to have LocalDb for SQL Server installed (Its all stated above and get both to make sure we won’t be encountering issues). Once your done installing, open your cmd and type the following:

  1. sqllocaldb create “v12.0” – Create the instance for Local Db on SQL Server 2014
  2. sqllocaldb start “v12.0” – Start the instance for Local Db on SQL Server 2014
  3. sqllocaldb.exe create v11.0 – Create the instance for Local Db on SQL Server 2012
  4. sqllocaldb.exe start v11.0 – Start the instance for Local Db on SQL Server 2012

The version number stands for the Local Db instance.

51

After this, I hope this solves your issue. Try creating your database again and it should work now.

*Issuance Checkpoint Ends Here*

 

8.1) Connecting the Database to the App through Connection Strings

Now that we have the database, we should let the app know we created it. Open up your Web.config and insert the following tag below the <appSettings>:


&amp;lt;connectionStrings&amp;gt;
    &amp;lt;add name="DefaultConnection" connectionString="Data Source=(LocalDB)\v11.0;&amp;nbsp;AttachDbFilename=|DataDirectory|\MyDatabase.mdf;Integrated Security=True"&amp;nbsp;providerName="System.Data.SqlClient" /&amp;gt;
&amp;lt;/connectionStrings&amp;gt;

90-3

 

Let me explain the tag and its attributes:

  • connectingStrings – This is where you establish connections from your database to the app. It contains a name under the <add> tag.
  • name – The name of the database context. In our case its DefaultConnection and we’ll use this name later in our app.
  • connectionString – the property that tells the where the database source is located. don’t get this confused from the upper tag as this is an attribute from the name. Inside it has 3 more attributes:
    • Data Source – This is the server name. In our case since we’re using a LocalDb which is only saved within Visual Studio, its (LocalDb)\\v11.0 and v11.0 means were using SQL Server 2012 LocalDb.
    • AttachDbFileName – This is where you’ll indicate the directory if your database file(.mdf). |DataDirectory| stands for the solution’s directory and beside it is the database name (in our case MyDatabase.mdf).
    • Integrated SecurityIf set to true, we’ll be using Windows Authentication mode(which is you’ll be using your windows account). If false, you’ll be required to place in 2 attributes which are UserId and Password. We set ours to true so as to not complicate the process.
  • provideName – We’ll place here the  Data Provider for SQL Server which we’ll use for data storage. By default its System.Data.SqlClient which is a .NET library for SQL Server.

Now that we have our database linked in to app. Let’s now create our database tables.

 

8.2) Creating the Database Tables

We’ll create 2 tables. One for the users and one for the list. Double-click on MyDatabase.mdf (located on App_Data folder) and it should open the Server Explorer on the left. From there, drop down the menu on the database until you see the Tables folder. Right-click it and Add New Table.

53

*Issuance Checkpoint*

If you cannot see the tables option from the dropdown, it means you don’t have SQL Server Database Toolings for 2013 installed. Click here to get it. After installing, restart your Visual Studio and Add new Table option should appear.

*Issuance Checkpoint Ends Here*

A  designer view should appear and on the T-SQL portion, type this following code:


CREATE TABLE [dbo].[Users]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY (0,1),
    [Email] NVARCHAR(50) NOT NULL,
    [Password] NVARCHAR(100) NOT NULL,
    [Name] nvarchar(100) NOT NULL,
    [Country] nvarchar (50) NOT NULL
)

54-2

 

Note that the table name is based after the schema name on the right inside the brackets []. We created 5 columns with their corresponding data types. IDENTITY (0,1) beside the primary key on ID mean that its set to auto increment. For each value added, the ID will chronologically increment by one. Note that it is possible to configure your columns through the designer portion but I placed the T-SQL code to ensure that you can follow. Click on the Update button located on the upper-left portion.

Then a Preview Database Updates windows will appear. Click on Update Database button below (the middle button) then your tables have been created.

 

You can double check if the tables have been created by refreshing the database on the Server Explorer. Right-click the database and click on refresh. You can see the table on the Tables folder.

55

Next, we’ll create another table named List. Repeat the process on how you created the Users table and refer to the T-SQL code below:


CREATE TABLE [dbo].[List]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY (0,1),
    [Details] NVARCHAR(100) NOT NULL,
    [Date_Posted] NVARCHAR(30) NOT NULL,
    [Time_Posted] nvarchar(50) NOT NULL,
    [Date_Edited] NVARCHAR(30) NOT NULL,
    [Time_Edited] nvarchar(50) NOT NULL,
    [public] NVARCHAR(5) NOT NULL

)

56

 

By now, you should have 2 tables. Refresh again your database from the Server Explorer then make sure to have those 2 tables within the folder:

 

57

Next step, We’ll use the Entity Framework to use queries and use for data manipulation from database to UI.

 

9.) Linking the Database Through Entity Framework

 

Let’s install Entity Framework in our App. Right-click on your solution (MyFirstWebsite) on the Solution Explorer then click on Manage NuGet Packages… This is pretty similar to what you did when you got the Owin Libraries. On the search bar, type in EntityFramework and install.

 

58

 

9.1) Creating the Context and Renaming the LoginModel

Once done, let’s create a class within the solution named MainDbContext

 

59

Next thing is we’ll rename our LoginModel into Users. Reason is because the class name should have the same name as the table name to let the app know its representation. When you rename, there will be a Red underline indicating that its name has changed:

rev1

 

Put your cursor there and select Rename ‘LoginModel’ to ‘Users’ on the dropdown (First option).

 

This will rename all everything linked to that into the same name although there is one limitation. It didn’t renamed the reference from Login.cshtml. If you recall, we’ve referenced our model there. Note that we only renamed that class, NOT the file name itself.  Make sure to rename the file as well so you wouldn’t get confused. Right-click on it and choose Rename. Rename it as Users.cs

rev2

 

Let’s go there and change its reference to @model MyFirstWebsite.Models.Users together with the code. We’ll replace EditorForModel() with the following:


@model MyFirstWebsite.Models.Users
@{
    ViewBag.Title = "Login";
}

&amp;lt;h2&amp;gt;Log In&amp;lt;/h2&amp;gt;

@Html.ValidationSummary(true)

@using (Html.BeginForm())
{
    @Html.LabelFor(u =&amp;gt; u.Email)&amp;lt;br/&amp;gt;
    @Html.TextBoxFor(u =&amp;gt; u.Email)&amp;lt;br/&amp;gt;
    @Html.LabelFor(u =&amp;gt; u.Password)&amp;lt;br/&amp;gt;
    @Html.PasswordFor(u =&amp;gt; u.Password)&amp;lt;br/&amp;gt;
    &amp;lt;p&amp;gt;
        &amp;lt;button type="submit"&amp;gt;Log In&amp;lt;/button&amp;gt;
    &amp;lt;/p&amp;gt;

}

70-3

 

We made the type specific because we are going to add more fields in the model. In this page, we only needed 2 fields which are Email and Password. We will be using the same model for user registration later on. We’ll also add in fields which are necessary for the database. Don’t worry, this doesn’t change the UI. Let’s modify again our Users and add Name and Country with our fields with the following code:


public class Users
{
    [Key]
    public int Id { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }

    public string Name { get; set; }

    public string Country { get; set; }

}

rev4

 

As you’ll notice, we’ve followed the database columns within out class. We deleted our ReturnUrl since its not needed anymore. We’ll be using it for our Entity Framework Later. 

Going back to our MainDbContext.cs, let’s add the libraries System.Data.Entity for our DbContext and MyFirstWebsite.Models to load up our model. Type the following on the class:


public class MainDbContext : DbContext
{
    public MainDbContext()
        : base("name=DefaultConnection")
    {
    }

    public DbSet&amp;lt;Users&amp;gt; Users { get; set; }
}

rev5

To explain the code:

  • base(<name of connection string here>) – This is where we link our database. The string inside is the name of the connection string. In our case its DefaultConnection. This might enlighten you:

65

 

  • DbContext – A class we inherited for MainDbContext to load the framework.
  • DbSet<Model> – This tells that this is a table representation and it the model name should be the same as the Table name in the database.

9.2) Cleaning our AuthController Redirection

Next, let’s clean out AuthController by removing the GetDirectUrl method and replace it with the following:

return RedirectToAction(“Index”,”Home”);

 

66

 Oh and don’t forget to remove this too as its not needed anymore:

70-2

 

This is simpler and easier. The method was only to show you how we pass values and use the URL we have to redirect.

 

10.) Creating the Registration Page

Next up is an interesting part. We’ll create the registration page where we can register more users for the page. First off, create a new action method named Registration inside your AuthController then together create a view for it. Same thing as others leave the view settings as is then add it. You should have the following:

67

AuthController.cs

 

68

Registration.cshtml

 

 10.1) Creating the Registration Action and View Page

Inside Registration.cshtml, type the following:


@model MyFirstWebsite.Models.Users
@{
    ViewBag.Title = "Registration";
}

&amp;lt;h2&amp;gt;Registration&amp;lt;/h2&amp;gt;

@using (Html.BeginForm())
{
    @Html.LabelFor(u =&amp;gt; u.Email)&amp;lt;br /&amp;gt;
    @Html.TextBoxFor(u =&amp;gt; u.Email)&amp;lt;br /&amp;gt;
    @Html.LabelFor(u =&amp;gt; u.Password)&amp;lt;br /&amp;gt;
    @Html.PasswordFor(u =&amp;gt; u.Password)&amp;lt;br /&amp;gt;
    @Html.LabelFor(u =&amp;gt; u.Name)&amp;lt;br /&amp;gt;
    @Html.TextBoxFor(u =&amp;gt; u.Name)&amp;lt;br /&amp;gt;
    @Html.LabelFor(u =&amp;gt; u.Country)&amp;lt;br /&amp;gt;
    @Html.TextBoxFor(u =&amp;gt; u.Country)&amp;lt;br /&amp;gt;
    &amp;lt;p&amp;gt;
        &amp;lt;button type="submit"&amp;gt;Register&amp;lt;/button&amp;gt;
    &amp;lt;/p&amp;gt;
}

70-6

Its just basically the same as Login.cshtml. It would be easier if you’ll just copy-paste it although there are some slight changes if you’ll notice. Its just the same information but added the name and the country.

 

10.2) Adding Data Encryption and Decryption

We’ll place in the code wherein we can add data based on users inputs. We’ll add another Registration Action but this time for and HttpPost. Type the following code:

[HttpPost]
public ActionResult Registration(Users model)
{
    if(ModelState.IsValid)
    {
        using(var db = new MainDbContext())
        {

        }
    }
    return View();
}

71

We’ve loaded up our MainDbContext inside the using so that we can dispose them at the end of the block. We need to dispose them so that our database is ensured to be safe. Its inside an if-statement wherein all models should have the correct format before it proceeds.

Next, we’ll create our own encryption library. From your solution, create a new folder (right-click MyFirstWebsite Add > New Folder) named CustomLibraries then inside it, create 2 new classes named CustomEncrypt and CustomDecrypt.

72

On CustomEncrypt.cs, add the following code:


using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace MyFirstWebsite.CustomLibraries
{
    public class CustomEnrypt
    {
        public static string Encrypt(string clearText)
        {
            string EncryptionKey = "MAKV2SPBNI99212";
            byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length);
                        cs.Close();
                    }
                    clearText = Convert.ToBase64String(ms.ToArray());
                }
           }
           return clearText;
        }
    }
}

73

 

What we’ve done is we created our Encryption class. I don’t need to explain it to bits as its function is to encrypt the string. This will be used for our password. Next let’s do the decryption by typing in the following on our CustomDecrypt.cs:


using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace MyFirstWebsite.CustomLibraries
{
    public class CustomDecrypt
    {
        public static string Decrypt(string cipherText)
        {
            string EncryptionKey = "MAKV2SPBNI99212";
            byte[] cipherBytes = Convert.FromBase64String(cipherText);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                   {
                       cs.Write(cipherBytes, 0, cipherBytes.Length);
                       cs.Close();
                   }
                   cipherText = Encoding.Unicode.GetString(ms.ToArray());
                }
           }
           return cipherText;
        }
    }
}

99-1
Now that we have the encrypt and decrypt functions ready, lets make our registration active and ready. Let’s go back to AuthController and modify our Registration action for HttpPost.

10.3) Creating the Query Logic

Add the reference using MyFirstWebsite.CustomLibraries so that the file knows we have a reference to our Custom libraries:

76

After, add the following code:


[HttpPost]
public ActionResult Registration(Users model)
{
    if (ModelState.IsValid)
    {
        using (var db = new MainDbContext())
        {
            var encryptedPassword = CustomEnrypt.Encrypt(model.Password);
            var user = db.Users.Create();
            user.Email = model.Email;
            user.Password = encryptedPassword;
            user.Country = model.Country;
            user.Name = model.Name;
            db.Users.Add(user);
            db.SaveChanges();
       }
   }
   else
   {
       ModelState.AddModelError("", "One or more fields have been");
   }
   return View();
}

75

Here’s the explanation to the code:

  • var encryptedPassword = CustomEnrypt.Encrypt(model.Password); – We’re encrypting our password using our library we created earlier assigning it to the variable encryptedPassword.
  • var user = db.Users.Create() – We’re creating the Users table within the code base so we can modify it.
  • db.Users.Add(user) – Adds the users object wherein its values where based from what we assigned from the model.
  • db.SaveChanges() – Saves the changes.

We’ll modify our navigation bar so we can navigate it through the page. On our _Layout.cshtml page, add the following code:

&amp;lt;li&amp;gt;
    &amp;lt;a href="@Url.Action("Registration", "Auth")"&amp;gt;Register&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;

77-1

 

We just basically added a hyperlink for the registration page. Now run the app, go to Auth/Registration and input some data. In my case, I’m adding the following data:

Email – admin@admin.com

Password – adminadmin

Name – Xtian

Country – Philippines

 

78

Click on register and it should now register. To check for the data, to to your server explorer, right-click on your database (the one named DefaultConnection) and on your tables, right-click Users table and show table data:

79

 

It should look like this:

80

 

10.4) Editing the Login Logic

Now that we have our code work dynamically with the database, we’ll modify our Login logic so that we’ll be using the database data instead of the hard-coded data earlier. On your Login action on AuthController.cs, Add on top of the if-statement using(var db = new MainDbContext()) encapsulating up to the redirect method.

99

Next we’ll add in the query logic together replacing the claims value. Make sure to have the library using MyFirstWebsite.CustomLibraries; on top for our decryption code and add with the following code:


var emailCheck = db.Users.FirstOrDefault(u =&amp;gt; u.Email == model.Email);
var getPassword = db.Users.Where(u =&amp;gt; u.Email == model.Email).Select(u =&amp;gt; u.Password);
var materializePassword = getPassword.ToList();
var password = materializePassword[0];
var decryptedPassword = CustomDecrypt.Decrypt(password);

if (model.Email != null &amp;amp;&amp;amp; model.Password == decryptedPassword)

99-4
Here’s the explanation to the code:

  • var emailCheck = db.Users.FirstOrDefault(u => u.Email == model.Email);This checks if the user has the same email as from the one in the database. This returns null as FirstOrDefault returns null if the following  condition isn’t met.
  • var getPassword = db.Users.Where(u => u.Email == model.Email).Select(u => u.Password); – Gets the password through LINQ query. If your familiar with SQL, its the same as “SELECT Password from Users WHERE Email == model.Email“.
  • var materializePassword = getPassword.ToList(); – Materializes the query into a readable list of array objects
  • var password = materializePassword[0]; – Since the query will only result to one result, we only have one array of result.
  • var decryptedPassword = CustomDecrypt.Decrypt(password); – Decrypts the password using our custom library.

This portion now verifies your email and password. Next, we’ll then modify your claim type values by placing in another query and replacing them with the following code:


var getName = db.Users.Where(u =&amp;gt; u.Email == model.Email).Select(u =&amp;gt; u.Name);
var materializeName = getName.ToList();
var name = materializeName[0];

var getCountry = db.Users.Where(u =&amp;gt; u.Email == model.Email).Select(u =&amp;gt; u.Country);
var materializeCountry = getCountry.ToList();
var country = materializeCountry[0];

var getEmail = db.Users.Where(u =&amp;gt; u.Email == model.Email).Select(u =&amp;gt; u.Email);
var materializeEmail = getEmail.ToList();
var email = materializeEmail[0];

var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, name),
new Claim(ClaimTypes.Email, email),
new Claim(ClaimTypes.Country, country)

99-3

Login with the data you used when you registered then type we’ll create our List inside the authenticated page.

11.) Create the List Table

We’ll modify the UI of our Home Page on Home/Index.  

11.1) Creating the UI for Tables

On your Index.cshtml, copy-paste the following code


@{
    ViewBag.Title = "Index";
    var username = User.Identity.Name;
}

&amp;lt;h2&amp;gt;@username's List&amp;lt;/h2&amp;gt;

&amp;lt;table class="table table-bordered table-condensed"&amp;gt;
    &amp;lt;thead&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Id&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Details&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Time - Date Posted&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Time - Date Edited&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Edit&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Delete&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Public Post&amp;lt;/th&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;a href="@Url.Action("Edit","Home")"&amp;gt;Edit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;a href="@Url.Action("Delete","Home")"&amp;gt;Delete&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
           &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;

113-1
 I guess there’s no need for me to print screen everything as this will give you an idea.

What we’ve done is we placed our tables on the client side and two hyperlinks, one for edit and one for delete.

Next we’ll create our model for the List so we can add items to the database.

 

11.2) Creating the List Model and Linking it to the Database

On your Models folder, create a new class and name it List.cs then after, add the following code inside it:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MyFirstWebsite.Models
{
    public class List
    {
        [Key]
        public int Id { get; set; }
        [Required]
        public string Details { get; set; }

        public string Date_Posted { get; set; }
        public string Time_Posted { get; set; }
        public string Date_Edited { get; set; }
        public string Time_Edited { get; set; }
        public string Public { get; set; }
    }
}

82-1

Same as above. The screenshot of the code is not complete but this should give you an idea.

Those properties are from the same as the List tables from the database. Next, let’s link this model so that we can use it for our Entity Framework.

On your MainDbContext.cs, add public DbSet<List> List { get; set; } below the Users DbSet.

83

Now we can use the List object for queries. Since we have that capability, let’s add an input field above the table so we can add our inputs to the database. 

Back to our Home.cshtml, add the reference @model MyFirstWebsite.Models.List on top of the code and the following code above the <table> tag:


@using (Html.BeginForm())
{
    &amp;lt;span&amp;gt;Enter new item: &amp;lt;/span&amp;gt;
    @Html.TextBoxFor(u =&amp;gt; u.Details)&amp;lt;br /&amp;gt;
    &amp;lt;span&amp;gt;Public post? &amp;lt;/span&amp;gt;&amp;lt;input type="checkbox" name="check_public" /&amp;gt;&amp;lt;br/&amp;gt;
    &amp;lt;input type="submit" value="Add Item"/&amp;gt;
}
&amp;lt;br /&amp;gt;

84-1
Your page should now look like this:

 

85-1

You might get surprised why aren’t we using our strongly-typed models for the public post? The reason is CheckboxFor needs to have a bool type. In our case, Our public field is a string so its not compatible. Instead, we are using the name in the input box where in check_public is assigned to it. Later I’ll show how to get data using from that implementation.

*Checkpoint*

Have you been asking yourself that if you are logged-in, you would see your own personal list but when you log-out and another person logs in, a different list would show up? Apparently this is the case of each user having their own personal list.

The relationship between the user and the list is one-to-one as a user can only have one list. From here, we need to compare something on the tables to know which row is his/her. The thing that we should compare is the ID as its unique and should never produce duplicate results.

In order to do this type of implementation, we’ll be needing to modify our List Table together with our List model. Let’s go to our Server Explorer and under MyDatabase.mdf, right-click the Tables folder then Open Table Definition.

It should open up the designer view of the table. on the T-SQL portion, add the following code to add the column User_Id and we’ll also make our Date_Posted, Time_Posted, Date_Edited, and Time_Edited into a nullable field since we’re not requiring it:

[Date_Posted] NVARCHAR (30) NULL,
[Time_Posted] NVARCHAR (50) NULL,
[Date_Edited] NVARCHAR (30) NULL,
[Time_Edited] NVARCHAR (50) NULL,
[User_Id] &amp;nbsp; &amp;nbsp; INT &amp;nbsp; NOT NULL,

Make sure to add it below public and add a comma at the end of the line. 

96

After, click Update (located on the top-left) then Update Database. Note that if there was a warning stating that you need a default value, just ignore it and continue to update the database.

 

On your List model (List.cs), add up the User_Id too with public int User_Id { get; set; }

88

 

Now that we’re done, we are set to do the logic for adding.

 

12.) Adding Items to our List 

On our Home Controller, add up the reference using MyFirstWebsite.Models so we can use our model object then create a new Index action for HttpPost with the following code:


[HttpPost]
public ActionResult Index(List list)
{
    if (ModelState.IsValid)
    {
        using (var db = new MainDbContext())
        {
        }
    }
    else
    {
        ModelState.AddModelError("", "Incorrect format has been placed");
    }
    return View();
}

89

Basically we placed a placeholder for model validation and loaded up the database object inside it together with the error message in case the user had the wrong format. Now on top of the database context, add the following code:


string timeToday = DateTime.Now.ToString("h:mm:ss tt");
string dateToday = DateTime.Now.ToString("M/dd/yyyy");

This will be used for our date and time posted. Add the library using System.Security.Claims since we will be using claims again and following code inside the database context:


using (var db = new MainDbContext())
{
    Claim sessionEmail = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email);
    string userEmail = sessionEmail.Value;
    var userIdQuery = db.Users.Where(u =&amp;gt; u.Email == userEmail).Select(u =&amp;gt; u.Id);
    var userId = userIdQuery.ToList();

    var dbList = db.List.Create();
    dbList.Details = list.Details;
    dbList.Date_Posted = dateToday;
    dbList.Time_Posted = timeToday;
    dbList.User_Id = userId[0];
    if (check_public != null) { dbList.Public = "YES"; }
    else { dbList.Public = "NO"; }
    db.List.Add(dbList);
    db.SaveChanges();
}

 

 

Here’s the explanation to the code:

  • Claim sessionEmail = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email); – Gets the Email ClaimType and assigned it to the variable sessionEmail. This is in a URL format os its not yet the value that we’re looking for. This was taken from AuthController, the part where we did our login module. Still recall that?
  • string userEmail = sessionEmail.Value; – Gets the real value of the claim, which now is the email address assigne to our variable userEmail.
  • var userIdQuery = db.Users.Where(u => u.Email == userEmail).Select(u => u.Id); – This is our LINQ query. LINQ is the query language for .NET frameworks. The value we’re getting here is not yet the real value as this always returns as a list. If you’re familiar with SQL, this query is equivalent to “SELECT Id FROM Users Where Email = userEmail“.
  • var userId = userIdQuery.ToList(); – Materializes the query and converts it into an array of strings.
  • userId[0]; – We should only have one result here as email addresses shouldn’t have duplicate data’s. Since userId is an array of strings, we then have a hard-coded value with an index of 0 which denotes the first value of the query.
  • The if statement checks whether we checked the checkbox or not the assigns the value YES or NO. The name came from the textbox name which we defined as check_public if you still recall.

Now let’s run the app and lets try adding some data.

 

*ISSUANCE CHECKPOINT*

Most likely you will encounter the error:

Model backing a MainDbContext has changed; Consider Code First Migrations

That’s because it relates to the other database you’ve seen earlier. Since everything is connected to the model, we added a new model called List and the other database (the migrated one) doesn’t have it. In order to solve this problem, we need to reinitialize the database. 

Now for the technical part, go to your Global.asax and add the library using System.Data.Entity and the following line of code:


Database.SetInitializer&amp;lt;MainDbContext&amp;gt;(null);

91

 Try running the app again and ONLY ONCE! It should reinitialize the DB again though take note that your your information from the Users table will be gone! I suggest go to the registration page and register again your credentials (Refer again to section 10.4). Don’t worry, we will only be doing this once as the List could be the last table (or model change rather) for this tutorial.

 *ISSUANCE CHECKPOINT ENDS HERE*

I’ll try input the following on the details:

Item: Salmon

Public post: Yes

 

92-1

*ISSUANCE CHECKPOINT*

Most likely you’ll encounter an error on db.SaveChanges() saying that dbo.Lists doesn’t exist. If that happens, we’ll simply rename the List into Lists (Yes we added letter s) in every parts we have them so that we don’t confuse the compiler. It got confused because List is a reserved word for giving out list of objects. Rename the following files:

List.cs model:

93

 

Your MainDbContext.cs

 

 

94

 

Index.cshtml on HomeController:

95

 

And lastly the database table itself (from the Server Explorer)

98

Try running the app again and add the Salmon with public data. It should now work.

*ISSUANCE CHECKPOINT ENDS HERE*

I’ll add the data twice so that we can have 2 items. We can check our database data and it should now appear on the tables:

100

13.) Displaying the Items to the List

Now that we successfully had our data in the database, we’ll display them in our UI. Let’s go back to our HomeController and edit our first Index action. Add the following code:


var db = new MainDbContext();
return View(db.Lists.ToList());

101

What this does is we’re returning all data from the Lists table. In SQL, its similar to “SELECT * FROM Lists“. Next, we’ll modify our Index.cshtml. Let’s replace 2 lines. One is our model reference we’ll make it to @model IEnumerable<MyFirstWebsite.Models.Lists> instead of @model MyFirstWebsite.Models.Lists so that it can receive the object returning from the controller. Another is we’ll replace the strongly typed input box into a regular HTML tag which is <input type=”text” name=”new_item”/> since our page can’t be strongly type due to converting our reference into an IEnumerable (a specific list for short).

102

Now that we’ve modified our text box for the details, we’ll also modify our home controller add the following code on the given portion:


string new_item = Request.Form["new_item"];

dbList.Details = new_item;

103

Going back to Index.cshtml, add the following code inside the <tbody> tag:


@foreach(var item in Model)
{
    &amp;lt;tr&amp;gt;
        &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Id)&amp;lt;/td&amp;gt;
        &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Details)&amp;lt;/td&amp;gt;
        &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Time_Posted)&amp;lt;/td&amp;gt;
        &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Time_Edited)&amp;lt;/td&amp;gt;
        &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;a href="@Url.Action("Edit","Home")/@Html.DisplayFor(modelItem =&amp;gt; item.Id)"&amp;gt;Edit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;a href="@Url.Action("Delete","Home")/@Html.DisplayFor(modelItem =&amp;gt; item.Id)"&amp;gt;Delete&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Public)&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
}

101-1
We’ve added a foreach to loop each row on the database. the Model in it is the object coming from the IEnumerable returned as a list then item is the variable assigned to it. Below it embeds the columns. Next we’ll edit our Lists model (List.cs) and remove the [Required] annotation from Details to avoid having a wrong valid ModelState:

106

Lastly, lets modify our return View in the HttpPost of the Index action and do the following:


var listTable = new MainDbContext();
return View(listTable.Lists.ToList());

107

This will prevent us from returning a null in our Index.cshtml during the loop

Now run the app and it should display the item. I’ll add Tuna and Fish as a non-public post to have another more items.

 

 Now that we can add and display items, next is Editing them.

 

14.) Editing the Items

Try hovering the Edit link on the right and you’ll see an ID:

108

It means we’re passing data through URL strings. its a sign that we should use an HttpGet. Lets modify our HomeController and add an action result named Edit for both HttpGet and HttpPost:


[HttpGet]
public ActionResult Edit(int id)
{
    return View();
}
[HttpPost]
public ActionResult Edit(Lists list)
{
    return View();
}

109

The id parameter gets the number from the URL you’ve seen earlier in the pic.

14.) Adding the Edit View

Next, create a view for the HttpGet, leave the settings as is and here’s the entire code:


@model MyFirstWebsite.Models.Lists
@{
    ViewBag.Title = "Edit";
    var username = User.Identity.Name;
}

&amp;lt;h2&amp;gt;Edit Details&amp;lt;/h2&amp;gt;
&amp;lt;a href="@Url.Action("Index","Home")"&amp;gt;Click here to go back&amp;lt;/a&amp;gt;
@using (Html.BeginForm())
{
    &amp;lt;span&amp;gt;Enter new item: &amp;lt;/span&amp;gt;
    &amp;lt;input type="text" name="new_item" /&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;span&amp;gt;Public post? &amp;lt;/span&amp;gt;&amp;lt;input type="checkbox" name="check_public" /&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;input type="submit" value="Add Item" /&amp;gt;
}
&amp;lt;br /&amp;gt;

&amp;lt;table class="table table-bordered table-condensed"&amp;gt;
    &amp;lt;thead&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Id&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Details&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Time - Date Posted&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Time - Date Edited&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Public Post&amp;lt;/th&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
   &amp;lt;tbody&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;@Model.Id&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;@Model.Details&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;@Model.Time_Posted&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;@Model.Date_Posted&amp;lt;/td&amp;gt;
            &amp;lt;td style="text-align: center;"&amp;gt;@Model.Public&amp;lt;/td&amp;gt;
       &amp;lt;/tr&amp;gt;
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;

113-2
Only partial of it at least to give you an idea

If you’ll notice, we did not use any IEnumerable as our reference as we’re not returning a lot of items and we’re not using the foreach for the same reason. Let’s add the following codes on top:


public static string date_posted = "";
public static string time_posted = "";

We’ll be needing this later when we persist our time and date posted.

Let’s modify our HttpGet action for Edit and add the following code:


var db = new MainDbContext();
var model = new Lists();
model = db.Lists.Find(id);
date_posted = model.Date_Posted;
time_posted = model.Time_Posted;
return View(model);

 

115-2

The code is pretty simple. We opened our db, declared the list object and passed values based on what was found. The Find() method accepts an integer which serves as the primary key of the table to search for the result.

Now run the app and you should have this page:

113-3

 

We have a hyperlink below to redirect us back to our home page if we changed our mind. Now for the fun part, lets go to our Edit action method for HttpPost and add the reference using System.Data.Entity. On the code, add the following:


var db = new MainDbContext();
string timeToday = DateTime.Now.ToString("h:mm:ss tt");
string dateToday = DateTime.Now.ToString("M/dd/yyyy");
string new_item = Request.Form["new_item"];
string check_public = Request.Form["check_public"];

if (ModelState.IsValid)
{
    list.Time_Edited = timeToday;
    list.Date_Edited = dateToday;
    list.Details = new_item;
    list.Time_Posted = time_posted;
    list.Date_Posted = date_posted;
    if (check_public != null) { list.Public = "YES"; }
    else { list.Public = "NO"; }

    db.Entry(list).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
}
return View(list);

115-4

 

I’ll input Cowfish as a non-public post then add. It should now display on your home together with the time and date edited:

114

Congratulations! We can now edit our list! Now off to the deleting feature.

14.) Deleting Items from the List

 

Next, we’ll delete the row from our list. We’ll create a new action named Delete. We’ll only need one as we’ll don’t need another page for confirmation but instead, we’ll make a confirmation box to make things faster and cleaner. On your HomeController, add one the following code:

[HttpGet]
public ActionResult Delete(int id)
{
    return RedirectToAction("Index");
}

116
We’ll put that as a placeholder for now. It accepts a query string for ID and returns back to our Index action.

Next we’ll add a confirmation prompt if the user wants to confirm the delete action. To do this, we need to edit our delete link. Go to your Home Index.cshtml, Replace it with the following:


&amp;lt;td style="text-align: center;"&amp;gt;&amp;lt;a class="pointer-arrow" onclick="deleteRow(@Html.DisplayFor(modelItem =&amp;gt; item.Id))"&amp;gt;Delete&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;

We removed the Url.Action as we’ll need to pass on the date to the deleteRow() function from the javascript wherein if the users clicks the row, we’ll pass the Id specifically on the given row.

Next, add the following code below the file table:


&amp;lt;script&amp;gt;
function deleteRow(id)
{
    var r = confirm("Are you sure you want to delete this record?");
    if(r == true)
    {
        window.location.assign("/Home/Delete/" + id);
    }
}
&amp;lt;/script&amp;gt;
&amp;lt;style type="text/css"&amp;gt;
    .pointer-arrow:hover {
        cursor: pointer;
    }
&amp;lt;/style&amp;gt;

 

117-2

Note: I didn’t created a separate JS/CSS file for those as I’m only demonstrating how it works. No need to make it complicating for now.

For the code, we created a confirm box wherein if its true, it will go to Home/Delete/{id} otherwise cancels the delete operation. The purpose is the style is when the user places the cursor on the Delete link, the cursor will change into a pointing finger. We need that because that property was lost as the attribute href was gone so we need to set it manually.

 

Now run the program then click delete on any row. It should display the alert box with 2 choices:

In this case, I’ve  clicked the second row

118

Next we’ll add in the delete logic. Let’s go back to our Delete Action and add the following code:


[HttpGet]
public ActionResult Delete(int id)
{
    var db = new MainDbContext();
    var model = db.Lists.Find(id);

    if (model == null)
    {
        return HttpNotFound();
    }

    db.Lists.Remove(model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

119

Pretty much the same as Edit’s but the only difference is using the Remove() method wherein we remove the data based from the Key Id. Another is an if-statement wherein it returns an error message if the row has been deleted. Now let’s try deleting the second row then it should get deleted.

In this case, I’ll delete 2 data’s which are Salmon with the Id ofand Tuna with the Id of 3. It should now delete. It shouldn’t display now.

120

Congratulations! We’re now done on the delete feature! Next, we’re off to our last feature, displaying public posts when the user is logged-out.

14.) Displaying Public Data

Let’s add some more data. I’ll add the following:

  • Tuna – Public
  • Shark – Public
  • Whale – Non-Public
  • Goldfish – Public

 

121

Logout from the system. From our AuthController, we’ll create a new action named Index for HttpGet and place it on top with the following code:


[HttpGet]
public ActionResult Index()
{
    var db = new MainDbContext();
    return View(db.Lists.Where(x =&amp;gt; x.Public == "YES").ToList());
}

122
Create a view for it then add the following code (Index.cshtml for Auth):


@model List&amp;lt;MyFirstWebsite.Models.Lists&amp;gt;
@{
    ViewBag.Title = "Index";
}

&amp;lt;h2&amp;gt;Public List&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;@Html.ActionLink("Click here to Login","Login")&amp;lt;/p&amp;gt;

&amp;lt;table class="table table-bordered table-condensed"&amp;gt;
    &amp;lt;thead&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Id&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Details&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Time - Date Posted&amp;lt;/th&amp;gt;
            &amp;lt;th style="text-align: center;"&amp;gt;Time - Date Edited&amp;lt;/th&amp;gt;
       &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
        @foreach (var item in Model)
       {
           &amp;lt;tr&amp;gt;
               &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Id)&amp;lt;/td&amp;gt;
               &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Details)&amp;lt;/td&amp;gt;
               &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Time_Posted) - @Html.DisplayFor(modelItem =&amp;gt; item.Date_Posted)&amp;lt;/td&amp;gt;
                &amp;lt;td style="text-align: center;"&amp;gt;@Html.DisplayFor(modelItem =&amp;gt; item.Time_Edited) - @Html.DisplayFor(modelItem =&amp;gt; item.Date_Edited)&amp;lt;/td&amp;gt;
          &amp;lt;/tr&amp;gt;
       }
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;

123-2

 

This displays the list of public rows. For the finishing touches, add <p>@Html.ActionLink(“Click here to view the public list”, “Index”)</p> on to your Login view so that you can navigate through the public list.

124

Now run the app and go to Auth/Index. It should now display the public data we’ve set earlier.

125

Congratulations! We are now done with the tutorials! Now we can use the app but we still need to clean up some messy parts. I’ll show you some loopholes that we got and we’ll clean them.

 

17.) Cleaning the Code

We have two loopholes to clean. One is we still have the Logout displaying on our header even though we’ve logged-out and two, we have to make some validations whenever registering our user so that only one unique user can exist in the table.

126

Go to your _Layout.cshtml and modify replace the logout portion with the following code:


@if(User.Identity.IsAuthenticated)
{
    &amp;lt;li&amp;gt;
        &amp;lt;a href="@Url.Action("Logout", "Auth")"&amp;gt;Logout&amp;lt;/a&amp;gt;
    &amp;lt;/li&amp;gt;
}

127

Lastly, go to your AuthController. Go to your Registration action for HttpPost and replace with the following:


var queryUser = db.Users.FirstOrDefault(u =&amp;gt; u.Email == model.Email);
if(queryUser == null)
{
    var encryptedPassword = CustomEnrypt.Encrypt(model.Password);
    var user = db.Users.Create();
    user.Email = model.Email;
    user.Password = encryptedPassword;
    user.Country = model.Country;
    user.Name = model.Name;
    db.Users.Add(user);
    db.SaveChanges();
}
else
{
    return RedirectToAction("Registration");
}

128

FirstOrDefault() returns a null if the conditions are not met. We did this so we can check if the user already exists in the database. Otherwise, it will continue with the registration.

Now run the app and the Logout on top should be gone and when we register an existing user, it should redirect you back to the registration page.

 

18.) Debriefing and Summary

In the end, you should have this file structure.

129

I guess I don’t need to picture out every file. As promised, I’ll be giving you the complete files in case you get lost or if you need references during/after development. Click here as its uploaded at my GitHub (Follow me too!). Check out my PHP Tutorial too! Follow me as well on Instagram and on Twitter and tweet me your feedbacks and experiences 😀

Credits to Ben Fosters blog for giving enlightenment on Identity, MSDN blogs for specific explanations and Stack overflow for explaining things in a nutshell.

Thanks and hope this helps you with your projects. Happy Programming!

106 thoughts on “Creating your ASP.NET MVC 5 Application from SCRATCH for Beginners: Using Entity Framework 6 and Identity with CRUD Functionalities

  1. you forgot to tell that the [allowanonymous] has been placed before the public class AuthController:Controller. when overlooked, this will cause problem on the login part

    1. Pretty much the term explains it and the hierarchy on where its placed defines that functions within the class are anonymous by default.

      Thanks for your feedback!

      1. Hi Kristianguevara
        I see that the “[AllowAnonymous]” added produces error “unauthorized”
        and does not allow me to get to the login page. when I remove it no error shows. Don’t know followed your instructions carefully. Some help

  2. Let me update my information. When I remove the filterconfig class in the global.asax.cs file the error goes away. what am I doing wrong.

    1. Hi George! May I know which part of the tutorial are you currently working on? Also, what version of Visual Studio are you using?

  3. i am getting error (“LoginModal is inaccessible due to its protection level”).
    can u explain why i m getting this please..

    1. You misspelled LoginModel to LoginModal (not you carried over it). Another is make sure its set to public. Protection level means its access level (public, private, protected, etc). Maybe yours had an assumption of public. Making it public could solve that issue.

  4. Hi Christian,
    Thanks so much for the tutorial! It is great.
    I’m a beginner and as I’m following the tutorial, am encounter an error at 6.1) Adding the HttpGet Login Method to the AuthController.

    ReturnUrl = returnUrl

    It said LoginModel does not contain a definition for ReturnUrl

    I look at the LoginModel.cs and it has a public string ReturnURL but not ReturnUrl ?

    How can I resolve this error?

    Thanks very much.

    1. Hello! That’s likely from your query string as it doesn’t contain a URL value. Check your browser’s URL and see if it contains any values. If none, you may have to double-check the code 🙂

    1. Hmm I see. Try double-checking the Startup.cs as it could be the potential file that can produce the error. If it still doesn’t work, try to download the entire project and if it’s flawless, from there you can retrace the steps.

  5. Hi Christian,
    I follow through and got the app to work. I have created three users but they all view the same list. The Users table each have an Id (1, 2, 3). The Lists table have 8 items but all the User_Id are the same which is 1.
    Seems like the Lists – Users relationship is not set?
    How can I resolve this issue?
    Thanks

    1. Hello! Try rechecking again your id values. That’s the most probable case I see as they might not be mapped properly.

  6. This is a really well thought out tutorial. Thanks for taking the time to compile this together. You really cover the gambit of programming one fell swoop.

  7. Hello, how are you? firstly, thanks for this amazing post!
    I was coding what you wrote, but I receive an error in the decrypt method :

    System.Security.Cryptography.CryptographicException: The input data is not a complete block.
    just in this part of code:
    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
    {
    cs.Write(cipherBytes, 0, cipherBytes.Length);
    cs.Close(); //here
    }
    what can it be the cause?

  8. Thanks Kristianguevara for this Awesome post. I was waiting for this. You have explained things just like bread and butter no one ever had. I followed the entire tutorial and it works great. Thanks a lot !

    1. Hi Nishant! Thanks for your comment and I really appreciate it! Hope this helped you to understand the fundamentals 🙂

  9. Thank you

    when I reach 6.1 keep hitting the get method and my model values are null
    what am I missing?

    @{
    ViewBag.Title = “LogIn”;
    }

    Log In

    @Html.ValidationSummary(true)

    @using (Html.BeginForm())
    {
    @Html.EditorForModel()

    Log In

    @Model.Email
    @Model.Password
    }

    public class AuthController : Controller
    {
    [AllowAnonymous]
    // GET: Auth
    [HttpGet]
    public ActionResult Login(string returnUrl)
    {
    var model = new Login { ReturnUrl = returnUrl };
    return this.View(model);
    }

    [HttpPost]
    public ActionResult Login(Login model)
    {
    return this.View(model);
    }
    }

  10. i was lost between msdn,asp.net web site,stackoverflow and codeproject. you saved my time with your very simple and powerful explanation about asp.net login, claims and identity.

    Thank you all.

  11. i was lost between msdn,asp.net web site,stackoverflow and codeproject. you saved my time with your very simple and powerful explanation about asp.net login, claims and identity..

    Thank you all.

  12. Hello,
    thank you for awesome tutorial, everythink works just fine!
    I want to ask, how set, that only user can edit/delete items which he actually created? I guess it should be easy while there is a reliationship between item and user.
    Thanks!

    1. Thanks too! Yes you can add use the user privileges for admin accesses for edit/delete. What you can do is you can add to your query something like db.Users.Where(u => u.userAccessLevel == model.userAccessLevel) and check if it matches their conformity. You can rate them into something like 1 = admin, 2 = user.

      1. Thank you for your quick response!
        I’ve got the idea, but I’m still in the beginning of learning ASP.net. Can you provide more complex step-by-step solution or maybe some links which will help me better understanding and solving problem? (I tried google a little bit, but always ended up with role system and so on, which I found bigger than my needs). Anyway, thank you. I’ll keep trying 🙂

  13. Thanks for a great tutorial! I’ve got a problem at 10.3. I’ve completed all the code you provide and when i try to test it by clicking on register and inputting information I get a break and an error saying

    “An exception of type’System.Data.Entity.ModelConfiguration.ModelValidationException’ occurred in EntityFramework.dll but was not handled in user code

    Additional information: One or more validation errors were detected during model generation:

    The break happens in AuthController.cs on this line

    var user = db.Users.Create();

    Can you help me figure out what has happened/

    Best wishes,
    Craig

    1. Hello! Thanks for your feedback and I really appreciate it! Regards your error, that means you have a problem with your Users model. Ensure your model properties are public, has get set, and you have the [Key] annotation written on top of the primary key field. If ever, you can refer to my Github account (linked at part 18), have a look on the finished repo and try to compare your code with mine. Hope that helps 🙂

  14. Hi! Thanks so much for this tutorial – it’s so helpful 😀

    Just a quick question – When I try and navigate App_Data > Add> SQL Server Database I can’t see SQL Server database? I have installed the Microsoft SQL Server Compact Edition and applied it to the solution but I still cannot see anything. I would be grateful if you could point me in the right direction!

    Thank you!

    1. Hello Laura! Thanks for leaving out your comment and I apologize for my late reply. To be honest I’m not sure about that by my gut tells me this has something to do with the SQL Server installation and version. Sorry if I can’t give you the exact solution but since you already have the server installed, maybe you can try playing around with it by connecting SQL Server and use it as the source of the database itself instead of the in-house DB within the project. Maybe this article can help (https://msdn.microsoft.com/en-us/library/z6sa01t4.aspx). Hope I helped! 🙂

    2. Laura, just in case you couldn’t figure it out, Right-click on the App_Data and choose Add –> New Item and then select SQL Server Database from the list of options

  15. Great Job, Please after login in using the hard coded userinfo, i’m not redirected to the login and I have typed exactly what’s there.

    Please help.

    1. Hello Refined! I’m not sure what you meant on “i’m not redirected to the login” but I’m just assuming you typed a wrong username/password and you want it to be redirected back the login page yet it didn’t happened. Thats likely on your middleware on the Startup.cs. Try to double-check your Web.config and make sure that its referenced properly. Retrace your steps from the middleware part and see which part you weren’t able to follow. If the problem still persists, you can download the entire project and try to compare from there. Hope that helps!

  16. simply i loved you explanation and thanks for all details.
    just i spend 1 hour entire article and i created my first asp.net mvc application.Thank you very much.

    1. It means your emails wasn’t saved on the claim. Try to double check your authentication layer. If problem persists, try to download my Github project and compare the changes. Maybe something you did something wrong during the process.

  17. hey, at very early stage i get this error, and i cant get over it
    A claim of type ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier’ or
    ‘http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovid
    er’ was not present on the provided ClaimsIdentity.

    To enable anti-forgery token support with claims-based authentication, please verify that
    the configured claims provider is providing both of these claims on the ClaimsIdentity
    instances it generates. If the configured claims provider instead uses a different claim
    type as a unique identifier, it can be configured by setting the static property
    AntiForgeryConfig.UniqueClaimTypeIdentifier.

    pls help 🙂

  18. hey, at very early stage i get this error, and i cant get over it
    A claim of type ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier’ or ‘http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider’ was not present on the provided ClaimsIdentity. To enable anti-forgery token support with claims-based authentication, please verify that the configured claims provider is providing both of these claims on the ClaimsIdentity instances it generates. If the configured claims provider instead uses a different claim type as a unique identifier, it can be configured by setting the static property AntiForgeryConfig.UniqueClaimTypeIdentifier.

    Line 6: @Html.AntiForgeryToken()

    pls help 🙂

  19. This is one of the greatest tutorial I have read about building asp.net mvc website from scratch so far! Thank you so much!

  20. good day sir…i have a problem on the part of Auth/Registration where you click to register it says TypeInitializationException was unhandled by user code in the MainDbContext.cs pointing to base(“name = DefaultConnection”)

    1. Hello Patrick! About your problem, that likely occurs on the connections string. Kindly double check if you typed it correctly. Make sure you follow the steps thoroughly and you didn’t missed out a single character. If it seems unresolvable, you can refer to the finished product, compare it and see which part you went wrong. Hope that helps!

      1. thanks for the reply i just change my connection string…another problem i encounter again sir in on the Index.cshtml on the db.SaveChanges(); it says An exception of type ‘System.Data.Entity.Infrastructure.DbUpdateException’ occurred in EntityFramework.dll but was not handled in user code.

  21. Thanks a lot for this wonderful tutorial. I learn’t a lot. As a beginner it’s difficult finding good materials with focus on beginners and coding from scratch. Thanks again i really appreciate.

    1. Hello Manish! You may use the Url.Action() for that. You can pretty much checkout a working example on part 6.4. Cheers!

  22. You from the Philippines too? 🙂 I was having a hard time finding tutorials from scratch that also include CRUD capabilities. Until I found this. I’m new to ASP MVC so this is very helpful. Although I’m having a little difficulty understanding some of the syntax but overall thank you for this wonderful tutorial!

  23. Hi Sir,
    At the beginning I got Server Error in ‘/’ Application. I solved that by adding “” to Web.config and it worked. But after adding [HttpPost] it keeps giving me “No owin.environment item was found in the context ” at request.getOwinContext () method. How should I solve that?

  24. Good day,

    I have a query regarding MVC, suppose i have 2 tables on my dbase, 2 tables has related to each other 1 to many relation. I already use join in my LINQ but how could i put the result of that join table in my view?
    saying(var x =(from y in _db.mytble join z in _db.myothertbl on y.id = z.yid select new mytblcombi{ yfield = y.id,yotherfiled=y.field,yotherfield1=y.otherield1, z.field = field,z.otherfield=otherfield}))

    do i have to create a class for mytblcombi?
    how could i call this on view? to output the result on the user

    thanks

    1. Hello cyber_daemon! In order to display the results of your join data to the view you need to return it as a list. In your example you already have a variable “x” which serves as the result of your query. Only thing missing is you need to materialize that into a list object by calling out .ToList().

      In other words, you should do something like this return View(x.ToList());

  25. Thanks, nice tutorial, it is important to understand basics so building an application from scratch makes perfect sense for learning purposes!

  26. Hi, why am I getting this error during registration that no one may seem to have an answer for as I google it.

    An exception of type ‘System.Data.Entity.Infrastructure.DbUpdateException’ occurred in EntityFramework.dll but was not handled in user code

    Additional information: An error occurred while updating the entries. See the inner exception for details.
    ON: db.SaveChanges();

    I am using:
    Visual Studio 2013
    EntityFramework.6.1.3
    Microsoft.AspNet.Mvc.5.2.3
    Microsoft.Owin.3.0.1
    Owin.1.0

    I am a ASP.NET – VB guy but I’m making a transition to ASP.NET MVC – C#

    Please any help would be gracefully appreciated.

  27. Hello Kristian,
    Good tutorial, i really wanted to learn MVC asp.net from scratch.
    I have a question, it’s pretty basic but maybe you can help me. When you give us a code to paste in the project, it appears like:
    &lt;table class=”table table-bordered table-condensed”&gt;
    &lt;thead&gt;
    &lt;tr&gt;

    Ofc it won’t work if i paste it into VS2013, so.. How can I convert the code you put to normal code instead of seeing the uncoded code?

    1. Hello Jonathan! That snippet of code are actually HTML entities. Unfortunately for some weird reason my website did not recognize these HTML entities as a result it displayed as raw data. In any case you can view the picture for the real (translated) code or worse case you can check out the finished project then compare your work from there (link is on the last part of this article). The code in your comment is simply translated as:

      Hope this helps!

  28. Hi!
    Our connection isn’t working in this project, it seems like the connection string is for the sql server 2012, how do we change it to the latest version?
    In the connectionsStrings in webconfig page.
    Thanks in advance!

  29. Hi, Thank you for this post it did work fine.

    Is there any chance to add register only for admin
    (removing register from home screen and adding admin roles so ony he can register people?

    1. Hello Jim thanks for your feedback! Yes you may! you’ll simply add an additional table like a privilege level in order to determine their capabilities. Say 1 is for admin, 2 is for user, etc.

  30. hiiii , i’m a beginner and i’m using VS 2015 Express i have stopped at the login check with mail and pass as when i put the action =(” index”,”home”) i got the url empty and it throws an exception : “An exception of type ‘System.ArgumentException’ occurred in System.Web.Mvc.dll but was not handled in user code

    Additional information: Value cannot be null or empty.” at this line :
    return Redirect(GetRedirectUrl(model.ReturnUrl));

    any help??

    1. Hello! It seems that you’re having troubles with your URL value. Double-check again the return URL value and see where it went wrong. If things really don’t go well you might want to check the complete source code and double-check your work from there. Make sure you have the packages installed properly!

  31. hello sir , thanks for ur tutorial , it helped me a lot , i have just one problem , in the delete part its not deleting the records

    1. Hello ili thanks for your feedback! If your delete is not working kindly double-check your code from top. Its likely just occurring on either the data you’ve passed on or the line of code that does the deletion. If things really don’t work I suggest to look into the complete source code (link on the last part) then double-check your work there.

    1. Hello Jeppe. Thanks for those recommendations! It would be a great help to people trying to figure out a better way of doing so!

  32. Hi Nice Article ! I am learned a lot of thing in this article thank you so much. I have a question i am using role management. 1) Admin 2) Manager 3) Salesman. How am i provide specific difference dashboard to each one. Please explain .Thank you

  33. Wow!

    Followed this article and most of my concepts regarding MVC framework are clear. Thank you so much.

    I was able to build a personal note web application based off your explanation.

  34. HI
    I’m new in MVC Asp.Net before I work webforms.
    My Question is how is good creating the connection with database in MVC.
    I want creating one ClassLibrary where creating EntityFramework the content from EF and model from EF I want using in MVC Web Project. When creating the Controller the connection with EF from ClassLibrary are creating EntityDB db=new EntityDB(); .

  35. Hey !!
    Thank you, Great article !!!
    I have one question.
    On the Index we get the list, using the following:
    public ActionResult Index()
    {
    var db = new MainDbContext();
    return View(db.Lists.ToList());
    }

    How would I order this by date poster ?

    1. Hello Lou thanks for your feedback! What you can do is you can add an additional method called OrderByDescending(). Example using date_posted field – db.Lists.OrderByDescending(a => a.Date_Posted).ToList()

  36. this is the best mvc tutorial I have ever read. there are lots of tutorial on net but all of them start to explain from template. and templates has lots of dummy files like views, controllers, js files and so forth. thanks for this lovely tutorial.

  37. Hello kristianguevara,

    AWESOME !!!
    As one of the replies said : I was lost between codeproject, msdn, asp website, and stackoverflow then I found this tutorial….

    I have one question (on problem) and one suggestion :

    – Suggestion : Those using a SQL SERVER instance (not the one built into VS ) should add the following
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {modelBuilder.Conventions.Remove();}

    – Question : I’m stuck at Login (step 10). Identity does get Authenticated. I can register a user. I can get its data backfrom the database. Password is encrypted and decrypted successfully… but identiy never gets authenticated therefore, return RedirectToAction(“Index”, “Home”); always redirects me to the login page… Looking in the debugger (breakpoint right on the above RedirectToAction), I saw that identity property IsAuthenticated remains set to false… So I guess authManager.SignIn(identity); never succeeds (in my case)…

    Any idea what the issue is and how we could resolve this ?

  38. Sorry to post again,

    http://i66.tinypic.com/2r5gw21.jpg -> this is an image of debugger in _Layout… You’ll see @user.authenticated is not true…. You’ll also see that Claims are empty though they where properly set in AuthController (did not add an image for that)… In both Login action and _Layout, debugger show IsAuthenticated property to be false…

    — Also, for my suggestion above, it is actually
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {modelBuilder.Conventions.Remove();}

  39. Hello I am so excited I found your weblog, I really found you by error, while I was
    browsing on Aol for something else, Regardless I am here
    now and would just like to say kudos for
    a tremendous post and a all round interesting blog (I also love
    the theme/design), I don’t have time to go through it all
    at the minute but I have saved it and also added your RSS feeds, so when I
    have time I will be back to read a lot more, Please do keep up the awesome job.

  40. Hi Kristian Guevara,
    Thanks for the tutorial!

    I have 1 question how can I display current user data and NOT from all users.

    I think that i need to change something in HomeController.cs
    example return View(listTable.Lists.ToList()); // return data but only for user who has logged in. And when he or she signs out show nothing.

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *