• .net CLI is only available from .net core. not the previous versions
Adding Indentity UI to existing MVC application
• Right Click on the project and add New Scaffolded Item..
• Select Identity and click Add
• Before you select the Razor pages you want to add, you need to select the layout for those pages.
• So select the layout you want to add. Select the default one first. Expand Views, Click on Shared and select _Layout.cshtml
• Add Data context class using the '+' Button: Prove the Db context like this : Appname.Data.DbContext
• Add user class using the '+' Button: Provide the name for the user class
• Select the Razor pages you need login, register, logout etc
• Click on add then it will be added inside the Area folder of the project
• ScafoldingReadMe.txt will open saying Identity is added.
• Because the Identity UI uses Razor pages, these need to be added into the application
• This is done in the configuration services in the startup.cs class
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
• Inside the Configure function in the startup.cs class add one more line just before app.UseAuthorization(); and after app.UserRouting();
app.UseAuthentication();
app.UseAuthorization();
• Add one more function inside the app.UserEndpoints function:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
• Now the login and register pages can be navigated by start without debugging and following links
• https://localhost:5001/identity/account/login
• https://localhost:5001/identity/account/register
Creating User class and Database
• Create user class: Go to Areas, Data then open the User class previously created.
• Now insert the properties for the class. eg.
[PersonalData]
[Column(TypeName = "nvarchar(100)")] //using System.ComponentModel.DataAnnotations.Schema; needed for this
public string FirstName { get; set; }
[PersonalData]
[Column(TypeName = "nvarchar(100)")]
public string LastName { get; set; }
• It can be seen that the DBContext file is created inside the Data folder of the Areas/Identity
• The DBContext is also auto injected inside the app in the IdentityHostingStartup.cs file.
• Now the database, go to appsettrings.json and update the connection string.
"ConnectionStrings": {
"MyAssistantDBContextConnection": "Server=(localdb)\\mssqllocaldb;Database=MyAssistant;Trusted_Connection=True;MultipleActiveResultSets=true"
"MyAssistantDBContextConnection": "Data Source=.;Initial Catalog=MyAssistant;Integrated Security=True",
OR
}
• Change the localdb, mssqllocaldb and database name
Database Migration
• Select the project, Go to Tools then Nget Package Maner and Package Manager Console(PM)
• Run following Script on PM: Add-Migration "Initial-Create" :=> Migration folder will be created within the project
• Run on PM: Update-Database :=> This will create database and table in the sql server.Along with the default columns in Table two new columns are created as mentioned the user class.
Add Login and Register pages into a tab using nested layout
• Right click on the pages folder inside Areas/Identity, add, new item select Razor Layout
• Name it as AuthLayout.cshtml
• Remove existing code
• Add following code:
@{
Layout = "/Views/Shared/_Layout.cshtml"; //inherit the master layout
}
@RenderBody()// render the respective page
@section Scripts{
@RenderSection("Scripts",required:false) }
//this is required for the connection between layouts. otherwise this error will appear:
An unhandled exception occurred while processing the request.
InvalidOperationException: The following sections have been defined but have not been rendered by the page at '/Areas/Identity/Pages/_AuthLayout.cshtml': 'Scripts'. To ignore an unrendered section call IgnoreSection("sectionName").
Microsoft.AspNetCore.Mvc.Razor.RazorPage.EnsureRenderedBodyOrSections()
• Add following code in Login.cshtml and Register.cshtml:
@{
ViewData["Title"] = "Log in";
Layout = "~/Areas/Identity/Pages/_AuthLayout.cshtml";
}
&
@{
ViewData["Title"] = "Log in";
Layout = "~/Areas/Identity/Pages/_AuthLayout.cshtml";
}
Add script to the page
For example if we want to highlight the selected tab (sign in/ sign up) jquery should be added and that should go to the @section Scripts section of the new layout (_AuthLayout). the code looks like as follows:
@section Scripts{
@RenderSection("Scripts",required:false)
<script>
$(function () {
var current = location.pathname;
$('.nav-tabs li a').each(function () {
var $this = $(this);
if (current.indexOf($this.attr('href')) !== 1) {
$this.addClass('active');
alert(current);
}
})
})
</script>
}
Add components to the Registration form
• Open Register.cshtml.cs (inside Areas/Identity/Pages/Account). Then add FirstName and LastName as follows inside public class inputModel:
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
• Add those attributes into the public async Task OnPostAsync(string returnUrl = null) function too in the same file:
var user = new MyAssistantUsers { UserName = Input.Email, Email = Input.Email, FirstName = Input.FirstName, LastName = Input.LastName };
• Now need to update the html page too so open Register.cshtml and add Text fields for First name and last name as follows before email:
<div class="col-md-10">
<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.FirstName"></label>
<input asp-for="Input.FirstName" class="form-control" />
<span asp-validation-for="Input.FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.LastName"></label>
<input asp-for="Input.LastName" class="form-control" />
<span asp-validation-for="Input.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
Email confirmation disabling:
• After every successful regisstration user need to confirm their email address. that can be desabled here in IdentityHostingStartup.cs by making it false:
services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores();
Showing logged user using _partiallogin.cshtml:
• add following in the top nav bar:
Login before entering homepage.
for that an authorization attribute need to be added to the controller
go to Home Controller file and add [Autorize] attribute at the begining as follows:
nmaespace MyAssistant.Controllers
{
[Authorize]
public calss HomeController:Controller
also import using Microsoft.AspNetCore.Authorization;
Now when the app is loaded it redirects to the login page immediately.
Avoid user to go to login or registration page using address after logged into home page
That can be done by adding a check inside OnGetAsync function of login.cshtml.cs and register.cshtml.cs files
public async Task OnGetAsync(string returnUrl = null)
{
if(User.Identity.IsAuthenticated){
Response.Redirect("/");
}
if (!string.IsNullOrEmpty(ErrorMessage))
{................
and same in register.cshtmls.cs
public async Task OnGetAsync(string returnUrl = null)
{
if(User.Identity.IsAuthenticated){
Response.Redirect("/"); //("/home") can also be used.
}
ReturnUrl = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
}
Forgot password page
This can be added by just adding new scaffolded item to the project, select the db context on the dialog windon and check identity/forgot password