Creating new project with asp.net Identity and Database First [duplicate] - asp.net

I need to integrate Asp.Net latest MVC version with an existing database which has an additional column String Address to table dbo.AspNetUsers
I need to create an instance ApplicationUser which has property Address.
Any idea how to do it?

A possible solution which works for me, basically I am able to integrate Asp.Net Identity User Profiles with an existing Database.
Getting the Asp.Identity Tables:
Create an MVC Project with Authentication Individual User Account
Open the DB listed under the DefaultConnection in Web.config. It will be called (aspnet-[timestamp] or something like that.)
Script the database tables using SQL Server Management Studio (attach database for mdc).
Alternatively use something like http://identity.codeplex.com/
Integrating with your existing db:
Insert the scripted tables into existing database in SQL Server Management Studio.
Customize and add relationships to ApplicationUser (if necessary).
Create new Web Project > MVC > DB First Project > Import DB with EF ... .
In IdentityModels.cs change the ApplicationDbContext :base("DefaltConnection") to use your project's DbContext.
Now you have the Asp.Identity Tables in your db with ER model in your application.
Asp.Identity Profile Adding new properties:
Enable Entity Framework Code First Database Migrations, just in VS go under Tools ‘Package Manager Console’,
Execute the command “Enable-Migrations”; Once we enabled the database migrations, we can go ahead and add new properties for our UserProfile
To Add new properties modify IdentityModels.cs file, example:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailID { get; set; }
}
Add New Migration
Once we added the properties, bring the Package Manager Console and execute the following command.
Add-Migration “YouMigrationName”
This command will generate a database script file, now execute following command to run this script file against the database.
Update-Database
Now, all the new properties will turn into table fields in the same database table.
I hope it can help others, if you have a better idea please let me know.

Take a look at these projects on GitHub:
https://github.com/kriasoft/AspNet.Identity - Identity Database Project + VS Template
https://github.com/kriasoft/AspNet-Server-Template - Sample / reference project
Which includes:
SQL Database Project Template for ASP.NET Identity 2.0
Entity Framework Database-First Provider(s)
Source Code and Samples

I had recently the same problem. I had an apllication created with DBFirst aproach and I needed to add Identity. This is what I did.
Install the next packages:
1. Microsoft.EntityFrameworkCore
2. Microsoft.EntityFrameworkCore.Design
3. Microsoft.EntityFrameworkCore.SqlServer
4. Microsoft.AspNetCore.Identity
5. Microsoft.AspNetCore.Identity.EntityFrameworkCore
6. Microsoft.AspNetCore.Aututhentication.JwtBearer
Do DbContext inherit from IdentityDbContext, like this:
public partial class BookStoresDBContext : IdentityDbContext
OnModelCreating I called the base constructor in order to avoid an error like "'IdentityUserLogin' requires a primary key to be defined"
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
}
As far as it was a created project the StringConnection was already there, if not add it.
On the Startup.cs configure Identity service on ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BookStoresDBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("BookStoreDB")));
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequiredLength = 5;
}).AddEntityFrameworkStores<BookStoresDBContext>()
.AddDefaultTokenProviders();
}
You can configure the Authetication service too
services.AddAuthentication(auth =>
{
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => {
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
RequireExpirationTime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Your key to encrypt"))
};
});
Then run the migration from the Package Manager Console
Add-Migration InitDb
On the migration file, remove all the migrationBuilder.CreateTable for the tables you already have in your Database
Update the Database from the Package Manager Console
Update-Database
Then you will see the Identity Tables on your db
I hope it result usefull 😁

Don't forget to add migrations and update the database. Otherwise it throws a dependecy injection exceptions for the identity.

public class MyUser : IdentityUser
{
public virtual MyUserInfo MyUserInfo { get; set; }
}
public class MyUserInfo{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class MyDbContext : IdentityDbContext<MyUserInfo> //Edited to MyUserInfo
{
public MyDbContext()
: base("DefaultConnection")
{
}
public System.Data.Entity.DbSet<MyUserInfo> MyUserInfo { get; set; }
}
Getting Profile information
When the User Logs in, you can display the profile information by doing the following
Get the current logged in UserId, so you can look the user up in ASP.NET Identity system
var currentUserId = User.Identity.GetUserId();
Instantiate the UserManager in ASP.Identity system so you can look up the user in the system
var manager = new UserManager<MyUser>(new UserStore<MyUser>(new MyDbContext()));
Get the User object
var currentUser = manager.FindById(User.Identity.GetUserId());
Get the profile information about the user
currentUser.MyUserInfo.FirstName

Related

Web API Add controller with CRUD operations for existing Azure table in Existing Azure db

My app performs Authentication with Asp.NET Identity.
The users logging in are stored in dbo.ASPNetUsers
A while ago, I used migrations to add another table called "Customer", but now the table is populated.
How can I add a controller to perform CRUD operations ONLY on existing "Customer"(the other tables have controllers) without dropping the table and risking erasing any of its content or any other content in the existing tables in the db.
What I tried so far:
Create class in Models folder called "Customer" to resemble the table columns
public class Customer
{
[Key]
public string ID {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
Add DbSetCustomers
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
// : base("DefaultConnection", throwIfV1Schema: false)
: base("MS_TableConnectionString", throwIfV1Schema: false)
{
}
public DbSet<Customer> Customers { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
}
Add new Controller of type Web API 2 Controller with actions using Entity Framework using model class Customer, with data context class as the default ApplicationDBContext (default option when creating controller, im assuming it uses my app connection string for the azure table).
When using the GET customers in POST, I get an error saying the database has changed since last migration, I Imagine this is because adding the DbSet Customers but I do not want to update migration because in the migration code, there is Drop Table command.
Is this right method?
Should I just change the migration script not to drop the table?
Please advise.
"Database has changed since last migration" , it s a way of EF telling that your migration history doesn't match with the tables.
EF's default database generation workflow creates a full script that will recreate your database every time you select Generate Database from Model, so if you execute it in your DB you will lose all your data. However, if you just create a new Entity and did not change the existing ones, then you can still generate database from your Model but then take that script and only run the part that creates the new table for your new entity.
You can take a look at the below link for further reference:
https://www.apress.com/gp/blog/all-blog-posts/secular-trends-for-the-cloud/12097630
https://social.msdn.microsoft.com/Forums/en-US/ed3ccb7e-5e89-4fd4-ae92-d641a5c5bd9a/entity-framework-model-first-make-changes-to-the-database-without-dropping-tables?forum=adodotnetentityframework
https://www.pauric.blog/Database-Updates-and-Migrations-with-Entity-Framework/
Hope it helps.

NInject and Migration using EF Core in Console app

I am using NInject container for Dependency Injection and Entity Framework Core as ORM. The setup is as follows:
DB Context Class
public TarantoContext()
{
}
public TarantoContext(DbContextOptions<TarantoContext> options)
: base(options)
{
}
public virtual DbSet<FileData> FileData { get; set; }
public virtual DbSet<FileExport> FileExport { get; set; }
public virtual DbSet<FileStatus> FileStatus { get; set; }
public virtual DbSet<FileType> FileType { get; set; }
public static string ConnectionString { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(ConnectionString);
}
}
Program.cs
TarantoContext.ConnectionString = configurationManager.DatabaseConnection;
I am reading the configuration from json and passing it to the DataAccess layer (to the context class). I have a few tables in my database and taking database first approach I created the necessary data models and completed the dbcontext class code. I am able to fetch the data without any problems. Now I want to add-migration (I may have more changes to existing tables and may create new tables) and ran the following in package manager console:
Add-Migration InitialCreate
which resulted in the following error because the connectionstring property is null
I can fix this by hardcoding the connectionstring in the OnConfiguring method which I have tried without any problems:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
// The connection string needs to exist in the migration project for the purpose of migrations. Comment it in production.
optionsBuilder.UseSqlServer(
"Data Source=temp;Initial Catalog=Demo;Persist Security Info=True;User ID=temp;Password=temp;MultipleActiveResultSets=True;");
//optionsBuilder.UseSqlServer(ConnectionString);
}
}
but I do not think this is the correct way of doing migrations. Moreover I am not sure how to handle the migrations in productions if I am unable to set the connectionstring in Program.cs or outside of the dbcontext class. What I am interested in is learning any design pattern which other developers are using to handle this situation. Any advise is greatly appreciated.
In ASP.NET Core, you can load the connection string while setting up services in the ConfigureServices method. Use the following code:
services.AddDbContext<ApplicationDatabaseContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly("....")));
Now, the GetConnectionString call will retrieve the connection string from you configuration file i.e. appsettings.json. To handle different connection strings for different environments, you can override the default app settings using a appsettings.<Environment>.json file like appsettings.Production.json.
More on this here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-2.2
Check out the relevant MSDN documentation pages for these things as they contain a lot of information.

EF not creating identity table when trying to create new database

I have 2 model classes:
Customer.cs with name and Id
Movies.cs with name and Id
I tried to run enable-migrations, but I got this error:
No context type was found in the assembly WebApplication2'.
Then I saw some answers on websites and people told to make a DBContext class. I do not have any DBContext class as I just made a new MVC project.
So, I tried to make a DbContext class of my own as follows:
{
public class MyDBContext:DbContext
{
public void MyDbContext()
{
}
}
}
Then I was able to run enable-migrtaions command and Migration folder was created with configuration.cs as follows:
internal sealed class Configuration : DbMigrationsConfiguration<WebApplication2.Models.MyDBContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(WebApplication2.Models.MyDBContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data.
}
}
}
Now when I run the add-migration Initialmodel the Up() and Down() methods are empty and there are no Identity tables.
Please help !
First off I suggest you refer to creating a new MVC project using Entity Framework. There are a lot of tutorials but here's the Microsoft one which is accurate and pretty complete:
Get Started with Entity Framework 6 Code First using MVC 5
It also includes a section on Migrations, however you don't need Migrations until you have a database and a model that's changing.
I would suggest backing out your Migrations until we're ready for them. Rick Strahl has a good article on how to back them out and get back to a clean state:
Resetting Entity Framework Migrations to a clean State
Finally, your DbContext class has to have a DbSet. A DbSet class is an entity set that can be used for create, read, update, and delete operations. With your DbContext class as it is, Entity Framework has no idea what to do or map.
Change your DbContext class to something like this:
{
public class MyDBContext:DbContext
{
public void MyDbContext()
{
}
public virtual DbSet<Movie> Movies {get; set;}
public virtual DbSet<Customer> Customers {get; set;}
}
This will allow you (say in a Controller) to do something like this to add a new Customer to the database:
var customer = new Customer { name = "John Smith" };
using(var context = new MyDbContext())
{
context.Customers.Add(customer); // adds the customer to the DbSet in memory
context.SaveChanges(); // commits the changes to the database
}
NOTE: I don't recommend creating a DbContext this way in a controller, in the first link on using EF6 with MVC 5 there are better ways.
Hope that helps.

How to access users when Identity project uses EF Core and Class Library uses EF6 with same database

We have a .NET Core project that uses Identity 3 and IdentityDbContext using EF Core for user management. The generated tables are stored in a common SQL server database that is also being used by another project in our solution that is a .NET 4.5.2 Framework DataLayer using EF6.
(Just some more background - the .NET Core project is an authorization server that uses OpenIddict to implement OpenIdConnect and Oauth2 and is configured with Identity so that we can save users to the database and login and authenticate)
Once we've authenticated, we make calls to our API end point. The API talks to a DataLayer that works with EF6. From this project I need to fetch the logged in user and work with users for various queries. Ideally, I wanted to use and extend the same AspNetUsers table.
I am wondering what the recommended approach is here? If I try to generate a User DbContext in the EF6 project I have to add a new migration and the scaffolding wants to create a new table - one that already exists in the database. I am a little unsure about having 2 separate contexts in 2 different projects and how these can "play nice" together.
I have handled similar scenario recently. I followed this approach.
I have a separate Class Library for Data Layer, which has Identity related Repositories/Stores, migrations and DbContext. The DbContext takes connection string from the host project.
.Net Core project has connection string specified in appSettings.json. This connection string points to same database. This project implements IdentityServer3 and acts as Token Service.
.Net 4.5.2 project has connection string specified in web.config . This also points to same database. This app gets token from .net core project and uses that Bearer Token to access other APIs.
I created another project to keep the Entities and this project is referenced in both .net core and .net hosts.
This way i have one common data layer for 2 host projects and 2 different service/business layers for 2 host projects. It is working nicely for me.
As EF 7.0 doesn't support seeding, I have a console app for seeding data into database. Even this console app accesses the same database through Data Layer.
So 3 different projects are accessing same database.
I can't share my code with public. I hope this helps.
I was able to get this to work. The main issue is that I just wanted to access my AspNetUsers table that was generated by Identity 3 in the DotNet Core project in my DotNet 4.51 DataLayer class library project.
I achieved this by creating a User.cs Entity class in the class library EF 6 project and making sure it's properties matched the columns from the Identity 3 generated ApplicationUser.cs class.
User.cs
public class User{
[Key]
public string Id { get; set; }
public int AccessFailedCount { get; set; }
public string ConcurrencyStamp { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public bool LockoutEnabled { get; set; }
public DateTimeOffset? LockoutEnd { get; set; }
public string NormalizedEmail { get; set; }
public string NormalizedUserName { get; set; }
public virtual string PasswordHash { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public virtual string SecurityStamp { get; set; }
public bool TwoFactorEnabled { get; set; }
public string UserName { get; set; }
}
I then set up an EntityConfiguration to map to the AspNetUsers table
UserConfiguration.cs
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
ToTable("AspNetUsers");
}
}
In my DbContext class I added a DbSet for my Users entity:
public virtual IDbSet<User> Users { get; set; }
I then ran the Add-Migration command to scaffold the changes. Once generated, I commented out the code and applied the migration to the database. This generates a row in the __MigrationsHistory table for the AspNetUsers table but doesn't try to recreate the table.
I was then able to successfully talk to the AspNetUsers table from the DataLayer EF6 project :)
Also it seems that I can also extend the AspNetUsers table with custom columns now by adding properties to my User.cs class and doing the migrations in the EF6 Datalayer project.

VS Community 2015 MVC Template - Cannot access custom model

I'm currently learning Asp.NET MVC, I have started with the Ouf of the Box template from Vs2015 but I am having problems getting data from custom table
Goal: My Goal is to add a contact list for the standard ApplicationUser using the following class:
public class UserContact
{
[Key]
public virtual int Id { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ApplicationUser Contact { get; set; }
}
I have also added the following to my Application User:
public virtual ICollection<UserContact> ContactsList { get; set; }
And the following line to my ApplicationDbContext:
public DbSet<UserContact> UserContacts { get; set; }
The problem is that when I try to access the USerContacts table from my custome controller ContactController using
ApplicationDbContext db = new ApplicationDbContext();
var UserId = SomUserID
db.UserContacts.Where(x => x.User == UserId)
The where clause does not get recognised at all. I have useed the commands
enable-migration
add-migration ContactsList
update-database
Which ran with no errors and the table is now in the database. But I am unable to access the table. why? what am I doing wrong?
Please note that according to VS it is as if the .Where function is not available on the DbSet in my case
And linq is imported as this is the standard when adding a new empty controller with Vs2015.
The Database was created during the update-database
But ApplicationDbContext : IdentiyDbContext class does not let me access any other tables including Contact class, so,
when I used in my controller
"db.UserContacts.Where < x => x.User == someID >();"
it doesn recognise what x.User is from the UserContact class.
EDIT: I found a stack overflow post where the user was missing a using statement:
using System.Linq;
DbContext -> DbSet -> Where clause is missing (Entity Framework 6)

Resources