Tuesday, January 17, 2017

Customize User Authentication using ASP.NET Identity

Introduction

In this demonstration, We try to create a basic ASP.NET web application. By default User class is created and Register/Login methods are implemented. Let's see how we can add new properties to User class and customize Register method as we want.

Create a web application

In this demo application, I'm using Visual Studio 2015 with .NET framework 4.5.2. and MVC5.

Create a web application by clicking on File -> New Project, Then following dialog appears.

Create a new ASP.NET Web application




























 Select MVC as the template to create the application. Don't change the authentication, leave it as it is. Default authentication is Individual User accounts

Select 'MVC' template






























ASP.NET application can have 4 type of authentication, default authentication type is Individual User accounts. For this demonstration, use default authentication type.

Let's see available user authentication types.

No Authentication - When application don't need any type of user authentication, go for this type.

Individual User Accounts - When the application needs to store user information in a sql server database and allows to login to the app using stored data or else using existing credentials in facebook, google, microsoft or other third party provider.

Work & School Account - If you want to authenticate application users through azure, active directory or office 360, better to go with account type authentication

Windows Authentication - When you want to authenticate users with their windows login, use this type. It's mostly suitable for internal/organizational applications

In this application, we plan to store user information in a sql server database and enable user registration and user login.

authentication types in a web application

















Web Application Structure


application structure looks like this.

web application structure
























Run the application and check Register & Login pages.

Create the database

Enable Migrations for the application

In the visual studio main menu, Go to Tools -> Nuget Package Manager -> Package Manager Console,
In Package Manager Console, type Enable-Migrations command to add migration classes.

Enable migrations






Define the connectionstring

Add the connectionstring in web.config file, point it to the sql server database.

Define the connectionstring for sql server database





<add name="DefaultConnection" 
connectionString="Data Source=.; Initial Catalog=userAuthentication;Integrated Security=True" providerName="System.Data.SqlClient" />

Update the database

Set AutomaticMigrationsEnabled property to true, By default it's false. Run the update command in package manager console, Database will be created.

Update the database























Database is Created

Open the Sql server management studio and view the database. 

database is created




















Expand AspNetUsers table and check available columns in the table.

AspNtUsers table


















Authentication implementation in the application

Register a new user in the application

Run the application and go to the User registration page. Register yourself in the application

User registration 




















Type a short (weak) password to test the length complexity of a password, It shows a message as follows. In default password policy, password should be at least 6 characters lengthier.

password length complexity





















Hit on Register button after entering password longer than 6 characters, It shows the following error. In default password policy, It has stated password should have at least non letter or digit character, password should have at least one digit and at least one uppercase character.


password complexity policy













Type a valid password into the password field and view the record inserted in the AspNetUsers table. user email field is recorded in Email and UserName column, password is stored as a hash value in PasswordHash column, unique user Id field is inserted per user.

records in AspNetUsers table




Customize Password Policies

In this application, We have used ASP.NET Identity 2.2.1 to implement user authentication. Let's see how we can override these existing password policies.

Change the password length complexity to 10 characters

By default when we create a web application with Identity 2, user password length complexity is 6 characters. Let's try to change it to 10 characters.

App_Start folder holds ASP.NET MVC configurations from MVC4 onwards. In previous versions of MVC, all the MVC configurations were defined in Global.asax file. 

App_Start folder contains BundleConfig, FilterConfig, IdentityConfig, RouteConfig and Startup.Auth classes.

Bundle Config registers css and javascript files in the application, then they can be minified.

Filter Config contains all the filters getting applied to action methods and controllers.

Identity Config file holds all ASP.NET identity related details like, how user authentication process happens.

Route Config file defines ASP.NET routes in a web application, It has a default route to manage the urls in the application.

Startup.Auth class holds user authentication settings, In this example, it has defined a user manager and sign-in manager with necessary requirements.

Go to ApplicationUserManager class in IdentityConfig, change the PasswordValidator property, set length to 10 characters.

constructor in ApplicationUserManager class









public class ApplicationUserManager : UserManager<ApplicationUser>
{
     public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store)
     {
        PasswordValidator = new MinimumLengthValidator(10);
     }


Go to the Create method in ApplicationUserManager class, In PasswordValidator property, set password length to 10 characters.

Change PasswordValidator property to accomadate 10 characters length password 














// Configure validation logic for passwords
 manager.PasswordValidator = new PasswordValidator
 {
   RequiredLength = 10,
   RequireNonLetterOrDigit = true,
   RequireDigit = true,
   RequireLowercase = true,
   RequireUppercase = true,
  };


In viewmodels, change the password length property as below.

We have to change length of the password field in these view models. Go to AccountViewModel class and change the Password length in RegisterViewModel & ResetPasswordViewModel classes. In ManageViewModel class, change SetPasswordViewModel  & ChangePasswordViewModel classes.

Change password field length to 10 characters













[Required] 
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 10)] 
[DataType(DataType.Password)] 
[Display(Name = "Password")] 
public string Password { get; set; }

Run the project and try with a weak password. Password should have at least 10 characters, If not validations errors comes up.

set password length to 10 characters





















Change password Complexity - Password must have at least one special character and one number


Go to ApplicationUserManager class in IdentityConfig class. Change Password validation property as below. Password requires a special character and a number.


change password validation logic













// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator 
 { 
  RequiredLength = 10, 
  RequireNonLetterOrDigit = true, 
  RequireDigit = true, 
  RequireLowercase = false, 
  RequireUppercase = false, 
 };

Run the application and check whether password complexity works fine.

password complexity check


















Password history validation - User can't enter last 3 passwords again.

When user change password or reset password we can check whether he is using his old passwords by referring to the history records of his passwords. By default this feature is not implemented. Let's try to implement it.

Create password history class to hold password history information. Password history table will be created from this class. Open IdentityModel class and create PasswordHistory class inside it.

password history table





























public class PasswordHistory {

 public PasswordHistory() 
 { 
     CreatedDate = DateTime.Now; 
 } 

 public DateTime CreatedDate { get; set; } 

 [Key, Column(Order = 1)] 
 public string PasswordHash { get; set; } 

 [Key, Column(Order = 0)] 
 public string UserId { get; set; } 

 public virtual ApplicationUser User { get; set; }

 }

Change the ApplicationUser class to hold password history. Initiate password history list inside the constructor.

modify ApplicationUser class to hold password history information
















public class ApplicationUser : IdentityUser 

  public ApplicationUser () : base () 
 { 
   PasswordHistory = new List<PasswordHistory>();
 } 

 public virtual List PasswordHistory { get; set; }


Open IdentityConfig class and go to ApplicationUserManager class and initialize a variable to hold password history limit.

ApplicationUserManager class

public class ApplicationUserManager : UserManager 
 { 
    private const int PASSWORD_HISTORY_LIMIT = 3;


Write a method to check whether new password is same as recent three passwords. If entered password is same as recent 3 passwords returns true, otherwise false.

check whether password is valid according to the criterias











private async Task IsPasswordHistory (string userId, string newPassword) 

  var user = await FindByIdAsync(userId); 
  if (user.PasswordHistory.OrderByDescending(o => o.CreatedDate)
      .Select(s => s.PasswordHash)
      .Take(PASSWORD_HISTORY_LIMIT) 
      .Where(w => PasswordHasher.VerifyHashedPassword(w, newPassword) !=                           PasswordVerificationResult.Failed).Any()) 
           return true; 
  return false;
 }

  Add user and password hash into PasswordHistory table.

Insert to password history table









public Task AddToPasswordHistoryAsync(ApplicationUser user, string password) 

  user.PasswordHistory.Add(new PasswordHistory() { UserId = user.Id, 
                           PasswordHash = password }); 
  return UpdateAsync(user); 
}


Write a method to change the password.

change password method












public override async Task ChangePasswordAsync (string userId, string currentPassword, string newPassword) 

  if (await IsPasswordHistory(userId, newPassword)) 
   return await Task.FromResult(IdentityResult.Failed("Cannot reuse old password")); 
 var result = await base.ChangePasswordAsync(userId, currentPassword, newPassword);        if(result.Succeeded) 
 { 
   ApplicationUser user = await FindByIdAsync(userId); 
   user.PasswordHistory.Add(new PasswordHistory() { UserId = user.Id, 
    PasswordHash = PasswordHasher.HashPassword(newPassword) }); 
   return await UpdateAsync(user); 
 } 
return result; 
}

Try to change password, enter one of previous passwords from most recent 3 passwords. If below error message comes, we have successfully prohibited it.
cannot reuse old passwords

















We have customized password policies according to our need. Let's see how we can customize existing User to hold new attributes.

Change table structure in ApplicationUser class

Add/Remove properties in ApplicationUser class

Let's say we want to add few properties into ApplicationUser class. If we look at existing properties for user class, It shows like this.

columns in AspNetUsers table




















We need to add DisplayName and Active fields into ApplicationUser, class. Let's see how we can do this. Go to ApplicationUser class in IdentityModel.cs file. Add attributes you want. (Active & DisplayName properties.) Update the database after adding new properties.

Add properies into ApplicationUser class











public class ApplicationUser : IdentityUser 

  public bool IsActive { get; set; } 
  public string DisplayName { get; set; 
}


Add a Foreign Key into ApplicationUser class

We want to add AccountId property as a foreign key into ApplicationUser class. Create Account class as below. It should have a collection of users. We have to update the database after adding new properies.

Account class

















public class Account 

  public int Id { get; set; } 
  public string Name { get; set; } 

  public virtual ICollection Users { get; set; } 
 }

Add a reference to Account class in ApplicationUser.

ApplicationUser class with reference to AccountId














public class ApplicationUser : IdentityUser
{

    public int AccountId { get; set; }

    public virtual Account Account { get; set; }

Add Account table into database context class as follows. Go to IdentityModel class and add Account table into ApplicationDbContext class.

Application db context class


public class ApplicationDbContext : IdentityDbContext  

 
   public ApplicationDbContext()
     : base("DefaultConnection", throwIfV1Schema: false)
    {
 
    }

   public static ApplicationDbContext Create()
   {
       return new ApplicationDbContext();
   }

    public DbSet Accounts { get; set; } 
 }


Add new properties into RegisterViewModel

Let's try to add new properties into RegisterViewModel class, Id, DisplayName and Active fields.

RegisterViewModel class





































public class RegisterViewModel 


 public string Id { get; set; } 

 [Required] 
 [EmailAddress] 
 [Display(Name = "Email")] 
 public string Email { get; set; } 

 [Required] 
 [Display(Name = "Display Name")] 
 public string DisplayName { get; set; } 

 [Required] 
 [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 10)] 
 [DataType(DataType.Password)] 
 [Display(Name = "Password")] 
 public string Password { get; set; } 

 [DataType(DataType.Password)] 
 [Display(Name = "Confirm password")] 
 [Compare("Password" , ErrorMessage = "The password and confirmation password do not match.")] 
 public string ConfirmPassword { get; set; } 

 [Display(Name = "Active")] 
 public bool IsActive { get; set; }

 }

Since we add new fields into Register view model, we have to add DisplayName, Active and Id fields into Register.cshtml view.

Add new fields into Register view
















@Html.HiddenFor(model => model.Id)


 <div class="form-group">
        @Html.LabelFor(model => model.DisplayName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.DisplayName, new { htmlAttributes = new { @class = "form-control" } })
        </div>
    </div>


<div class="form-group">
        @Html.LabelFor(model => model.IsActive, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-12">
            @Html.CheckBoxFor(model => model.IsActive, new { htmlAttributes = new { @class = "form-control" } })
        </div>

    </div>

We have to change Register method bit according to our requirements. Go to Register method in Account controller. In this code sample, accountId field is coded as 1. If application can't find a valid account, it should show an error message. If account is found, create user in the system. If user creation is successful, sign in the user into the application, If not show validation messages.

Register method in Account controller 



// 
// POST: /Account/Register 
[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public async Task Register(RegisterViewModel model) 

  if (ModelState.IsValid) 
  { 
     var context = new ApplicationDbContext(); 
     ApplicationUser applicationUser; 
     //you can try to get accountId field from session 
     int accountId = 1; 
     Account account = context.Accounts.Find(accountId); 
     if (account != null) 
     { 
       applicationUser = new ApplicationUser { UserName = model.Email, Email = model.Email, AccountId = account.Id, IsActive = model.IsActive,
         DisplayName = model.DisplayName}; 
       var result = await UserManager.CreateAsync(applicationUser, model.Password); 
       if (result.Succeeded) 
       { 
         await SignInManager.SignInAsync(applicationUser, isPersistent: false,                                                      rememberBrowser: false); 
         return RedirectToAction("Index", "Home"); 
       } 
       AddErrors(result); 
       return View(model); 
     } 
     AddCustomizeError("Account Code Not Found."); 
   } 
return View(model); 
}

To display customized errors like 'Account Code Not Found.', We have to write a helper method as below.

helper method to catch model errors










private void AddCustomizeError(string error) 

  ModelState.AddModelError(error, error); 
}

Try to register a new user into the system, It shows following error message. It's a customized message, added into model state. Run some test scenarios and check whether all the other validations messages are showing properly.

User registration - Account code not found



























Go to Configuration class and add this line of code in Seed method.

Seed method in Configuration class







protected override void Seed(userAuthentication.Models.ApplicationDbContext context) 

  context.Accounts.AddOrUpdate(account => account.Name, new Account { Name = "Account1" }, new Account { Name = "Account2" }, new Account { Name = "Account3" }); 
}

Now try to login to the system. After you logged in, view the database. You can see DisplayName and Active coulmns in the AspNetUser table.

account and AspNetUsers table



Sunday, December 25, 2016

TechNet Guru Awards November 2016

TechNet Guru Awards November 2016 - C# - Bronze medal


I won the Bronze medal for my C# article on November TechNet Guru competition ðŸ˜€ðŸ˜€

Article : ASP.NETCore: Create a Web API application

Code :
    TechNet Gallery :  Create a web api application in .NETCore
    GitHub : fav-movies




Wednesday, November 30, 2016

Create a web application in.NETCore with a Linux server


Create .NET Core web application


Let’s see how to write a web application in .NETCore

Create a new project










dotnet new

code .

Create a new project and open it in Visual Studio Code.











Create a WebHostBuilder instance, since we need a server to run our web application, It’s little bit different to a Console application.

We get an error here, Some packages seem to be missing, ok!!! First of all let’s add a server to run our application.

Add Kestrel to our package list




















"Microsoft.AspNetCore.Server.Kestrel": "1.0.1"

Add Kestrel server into project.json file and restore the package.





















In program.cs file, Add relevant using statement.

























When initiating a WebHostBuilder, It turns your console application into a web application.

Now, Ask the host to build using Build method, and run the web host. When hit on Run method, It’s going to give a signal to the host to listen on a port and start accepting HTTP traffic.

Let’s run and see the changes















public class Program
 {
 public static void Main(string[] args)
 {
  Console.WriteLine("Hello World - web");
   var host = new WebHostBuilder()
            .UseKestrel()
            .Configure(app =>
                {app.Run(c => c.Response.WriteAsync("Hello"));
                })
            .Build();
    host.Run();
   }
 }

When we run our application, It gives an error!!!!

It says we haven’t provided a service to startup the application. It means we haven’t mentioned we want to use Kestrel or not when starting our application. Let’s check how we can start our application with kestrel server,

















In here we asked Kestrel to accept a HTTP request and turn it into a HTTP context. In configure, we accept an Application Builder instance, it’s going to perform some actions in our application.

When hit on app.Run(), It’s going to add a terminal to the HTTP request pipeline. Inside app.Run() method, we pass an HTTP context object kestrel has created.

In the terminal window, It shows Hello World - web .

Then it shows Hosting Environment as production., default hosting environment for a .NETCore application.

Then it shows Content root path of our application,

web project listen into http://localhost:5000/ which is default url and the default port of our application.

Wednesday, November 23, 2016

ASP.NETCore: Create a Web API application


1. Introduction


This article will walk you through on building a simple web API service using .NETCore. Service is extended to interact with a SQL server database in a windows PC and then modify the same service to work with a MYSQL database in a Linux server.


2. Background



3. Prerequisites


In this article, we are working with two environments, Windows and a Linux environment. Check whether you have installed these prerequisites before you start.

In Windows environment,
In Linux environment,

I have used Entity framework Core to access data from databases, necessary references to EFCore is installed in next steps.


4. Create a Web API application in .NETCore


Let’s try to create a .NETCore application from Visual Studio 2015





























Create a new project from Visual Studio 2015, In .NETCore tab, select ASP.NET Core Web Application (.NET Core) . Give it a name and click on OK.



























Select Web API from ASP.NET Core templates and click on OK.





















Check folder structure of the application, It includes a Program.cs and Startup file. It includes a project.json file to define all required packages for your application. appsettings.json file maintains application settings same as web.config file in a ASP.NET Web application. Controllers folder has all Web API Controllers.


4.1. Open service application from Visual Studio Code.

















cd into the application directory and open Visual Studio Code using code . command. You can see folder structure of your application as above. Add assets to build and debug your application as the info dialog box suggests.










vscode folder is added into the solution with launch.json and tasks.json file.


4.2. Dependencies in project.json file


Let’s see what are the dependencies required for a mvc application.














Since We create a Web API application, in project.json file, It shows Microsoft.AspNetCore.Mvc package dependency.


4.3. Run ValuesController and check service calls.


Let’s run Web API application and check available services.





























Build (Ctrl + Shift + b) and run (Ctrl + F5) your application and ping to the Read service as above. Its shows return values in the browser.


4.4. Let’s build the movie service


In this solution, Movie service is accessing a SQL Server database on windows, and later the same application with less modifications, going to access a MYSql server database in a Linux server


4.4.1. Create Movie model






















namespace movieStore.Models
{
 public class Movie
  {
    public int ID { get; set; }
    public string Title { get; set; }
    public string Director { get; set; }
    public int Year { get; set; }
    public string Language { get; set; }
    }
}

Create a Model folder to define entities in your application. Then create Movie class and add properties into it. We follow Code First approach in this example. So when we create the database Movie table will be created.


4.5. Create Movie service with SQL server on Windows.

4.5.1. Create Context class to build the database.












namespace movieStore.Models
{
    public class MovieDbContext : DbContext
    {
        public MovieDbContext(DbContextOptions<MovieDbContext> options) : base(options)
        {
        }
        public DbSet<Movie> Movies { get; set; }
    }
}

From context class, our database will be generated. Context class should be inherited from DbContext class. In order to do that, we have to add references from Entityframework core.


4.5.2. Install Entityframework Core (EF Core)








Add entityframeworkcore reference as a dependency into project.json file, “Microsoft.EntityFrameworkCore”: “1.0.0” and resolve reference error in MovieDbContext class by adding using Microsoft.EntityFrameworkCore statement.


4.5.3. Define the connectionstring










Define the connectionstring in appsettings.json file to connect to the Sql server,

“ConnectionStrings: { “DefaultConnection”: “Data Source=localhost;Initial Catalog=movieDB;Integrated Security= true” }


4.5.4. Check MovieDbContext class


















In MovieDbContext class, define constructor with context options and call base class method.


4.5.5. Add entities in moviecontext class






Try to run migrations for MovieDbContext class,
 
 dotnet ef migrations add InitialMigration

It gives an error,

No executable found matching command “dotnet-ef”

We have to install entityframeworkcore tools to run migrations from .NET cli. Let’s try to do that.


4.5.6. Add EFCore tools








Add EFCore tools in tools section of project.json,

 "Microsoft.EntityframeworkCore.Tools" : "1.0.0-preview2-final"

Try to run migration and it gives an error again!!,

Could not invoke this command with the startup project ‘demo’. Check that ‘Microsoft.EntityFrameworkCore.Design’ has been added to “dependencies” in the startup project and that the version of ‘Microsoft.EntityFrameworkCore.Tools’ in “tools” and ‘Microsoft.EntityFrameworkCore.Design` are the same. See http://go.microsoft.com/fwlink/?LinkId=798221 for more details,

We haven’t added EFCore Design as a reference, We have to add EFCore Design references to run migrations scripts. Let’s add it and check. And also it mentions ‘Microsoft.EntityFrameworkCore.Design’ and ‘Microsoft.EntityFrameworkCore.Tools’ version should be same.


4.5.7. Add EFCore Design reference.








Add EFCore Design reference into project.json file. Note that, `Microsoft.EntityFrameworkCore.Design' and `Microsoft.EntityFrameworkCore.Tools' version are same.

 "Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final"

Then try to run migrations command again and it gives another error,

No parameterless constructor was found on ‘MovieDbContext’. Either add a parameterless constructor to ‘MovieDbContext’ or add an implementation of ‘IDbContextFactory‘ in the same assembly as ‘MovieDbContext’.


4.5.8. Startup class implementation









public void ConfigureServices(IServiceCollection services)
   {
         services.AddDbContext<MovieDbContext>(options =>                                                                                                                            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// Add framework services
services.AddMvc();
}

In Configure services method, it’s going to add some services into the application.

services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”)));

Add the database context and define the connectionstring of your database, in configure service method, it’s missing some references, since we haven't add any EntityframeworkCore sqlserver references.


4.5.9. Add EFCore Sqlserver references








Add EFCore Sql server reference in project.json file and restore them.

 “Microsoft.EntityFrameworkCore.SqlServer”: “1.0.0”

















Now sqlserver reference is added. Configure service method looks fine.


4.5.10. Run Migrations


Let’s create movieDB in sql server.
















Run Sqlserver migrations, It doesn’t give any errors in .NET CLI, Migrations folder is created with migrations scripts. In Initial Migration class, it defines Up and Down methods to create and drop movie table respectively.


4.5.11. Update the database









run commands to update the database. In sqlserver, movieDB got created.

 dotnet ef database update



4.5.12. Add Movie controller


In Visual studio code, We can’t use scaffolding. So i created a Movie Controller with all the CRUD operations of Movie entity in visual studio. Let’s add it.
























In Movie Controller, it works with application/json type data, and the route is api/Movies. Note that in .NET Core Api controllers inherit from Controller class, not from API Controller class.























Go to api/movies method and check Network tab in developer tools. method returns 200 - OK. as a response. We don’t have data in movie database, Let’s try to add some data.


4.5.13. Add data using Postman














Postman is a tool to test your service apis. Although we can test GET requests through browser, to test POST requests, we need to use Postman. Add a movie using Postman and retrieve it using web browser.

We have created a service API using .NETCore and SQLServer. Let’s try to run this same application on Ubuntu with MySQL.


4.6. Change Movie service to work with MYSQL on Linux server.

4.6.1. Clone your application in Ubuntu


Let’s try to open your application in Ubuntu, We are going to connect this application to MySQL server,











Type git clone … with repository url, Your project will be downloaded. Then cd into application directory and open it in visual studio code.


4.6.2. Restore packages and build your application












Restore packages defined in project.json file and Build your application. It all works fine.


4.6.3. Let’s try to run the application

















Let’s try to run our application without any modifications, It seems working fine. Let’s navigate to api/values , It calls READ service of Values service. It returns 200 - OK as response.















Ping to api/movies, it returns an empty array, since we don’t have a database.

Check the terminal and try to find any errors, It shows a fail error in red. It says 'Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory[1] An exception occurred in the database while iterating the results of a query. System.NotSupportedException: The keyword ‘integrated security’ is not supported on this platform. at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString) …'

It says an error as The keyword ‘integrated security’ is not supported on this platform. If you remember, where we have used integrated security , that’s in sql server connectionString. We can’t operate with Sql server on Ubuntu. We have to install My SQL server to store data in your application. Let’s do that.


4.6.4. Add MySQL connectionString







Add mysql connectionString in appsetings.json file, movieDB will get created in mysql server.

 "DefaultConnection" : "server=localhost;database=movieDB;uid=root;pwd=hansamali;sslmode=none;"


4.6.5. Add MySQL service in your application

















If you remember, we added Sql service into the application when we run in Windows. In Ubuntu also same thing we have to do. Add MySQL service into your application with dbContext class. But it seems we are missing something in here.

Note that, Microsoft.EntityframeworkCore has been highlighted. Your application doesn’t use that reference anymore. It’s a reference from Sql server. We have to add a reference from MySQL to proceed with this. Let’s try to add it.








Add MySQL EFCore reference in project.json file and restore it.

“MySql.Data.EntityFrameworkCore” : “7.0.4-ir-191”

Add necessary changes in ConfigureServices method in Startup class.















services.AddDbContext(options =>

options.UseMySQL(Configuration.GetConnectionString(“DefaultConnection”)));

Add necessary using statements in startup class.

using MySQL.Data.EntityFrameworkCore.Extensions;

In windows with Sql server, We run migration scripts and ensure database is created. But with Ubuntu, we can’t do that. Somehow we have to ensure our database is created. Let’s give it a try.


4.6.6. Ensure MySQL database got created












Add this lines of code to ensure MySQL database got created.

var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseMySQL(Configuration.GetConnectionString(“DefaultConnection”));

var context = new MovieDbContext(optionsBuilder.Options);
context.Database.EnsureCreated();


4.6.7. Run your application




















Then build and run the application, navigate to movies read service and verify it works fine. read service returns empty array. Let’s check database is created in MySQL server.


4.6.8. View MySQL databases



























run commands to access mysql shell,

 mysql -u root -p

type command to view all the available databases, you can see movieDB is successfully created.

 show databases;


4.6.9. Let’s add some data into Movie database in MySQL





























Call POST service in movie controller and add a movie into the mysql database. Refresh read movie service, it shows available movies in your mysql database.

Connect to the mysql shell and try to view data in Movies table.

Go to mysql shell by typing this command,
 
 mysql -u root -p


view available databases

 show database;

type following command to go inside a database and query it

 use movieDB;

You can see available tables in movieDB using this command

 show tables;

Type a select query to view data in movies table

 select * from Movies;

In this post, I described how to run a web api application in windows with Sqlserver. And then we tried to configure same service application on Ubuntu with MySql server, with less amount of coding we could achieve that. It was a really cool feature in .NETCore


5. Download


5.1. TechNet Gallery

5.2. GitHub



6. Conclusion


In this article as you saw, we could modify same .NETCore application in both environments, Windows and Linux. We worked with two different databases SQL server and MYSQL, with Entityframework Core. I hope EFCore will provide its features for Oracle soon. Since .NETCore is cross platform and open source building applications for multiple environments is possible today.


7. References