'IdentityBuilder' does not contain a definition for 'AddEntityFrameworkStores' when upgrading to .NET 5 - asp.net

I'm trying to upgrade my .Net core 2.2 application to .net 5.0
This line no longer works:
services.AddIdentity<ApplicationUser, IdentityRole>
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
I get the message:
'IdentityBuilder' does not contain a definition for
'AddEntityFrameworkStores' and no accessible extension method
'AddEntityFrameworkStores' accepting a first argument of type
'IdentityBuilder' could be found
So based on my research I tried:
services.AddIdentity<ApplicationUser, IdentityRole>
.AddUserStore<DataContext>()
.AddDefaultTokenProviders();
However, while this compiles I get the following error at runtime:
Implementation type 'motorsport.Models.DataContext' can't be converted
to service type 'Microsoft.AspNetCore.Identity.IUserStore`
This is my DataContext:
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{ }
public virtual DbSet<ApplicationUser> ApplicationUsers { get; set; }
public virtual DbSet<RefreshToken> RefreshTokens { get; set; }
}
What am I doing wrong? Note that my application is API only, I'm not using Razor Views at all.

You need to install Microsoft.AspNetCore.Identity.EntityFrameworkCore which provides types for persisting Identity data with Entity Framework Core.
Because AddEntityFrameworkStores has been moved into separate NuGet package Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Related

.Net Core Add Migration Error - unable to create an object of type 'DataContext'. For the different patterns supported at design time

I am developing simple API project using .NET Core 6. This is the application structure.
Project Solution
StudentAPI (Main project - .NET Core Web API)
StudentAPI.DataAccess (Data Access Layer - created .NET class library)
StudentAPI.Models (This class library contains models ex: student/grade/address/course)
This is my Data Context Class (StudentAPI.DataAccess)
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Course> Courses { get; set; }
public DbSet<Address> Addresses { get; set; }
public DbSet<Grade> Grades { get; set; }
}
This is my Program.cs class (Main project - .NET Core Web API)
using Microsoft.EntityFrameworkCore;
using StudentAPI.DataAccess.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<DataContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
This is the appsetting.JSON file (Main project - .NET Core Web API)
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Server=.; Database=dotnet-rpg-test; Trusted_Connection=true;"
}
}
I tried to add initial migration using below command
dotnet ef migrations add 'Initial' --project .\StudentAPI.DataAccess
But I got below error message when I tried to add migration.
Unable to create an object of type 'DataContext'. For the different patterns supported
at design time, see https://go.microsoft.com/fwlink/?linkid=851728
Here I have selected StudentAPI (Main project - .NET Core Web API) as StartUp project and in package manager console selected StudentAPI.DataAccess as default project.
Kindly someone can tell me the why I am getting this error. I just want to divide my project into separate layers. And please tell me how to resolve this issue.Thanks.

.NET Core 2.2 to 3.1 Azure functions project migration build fails

I have a .NET Core 2.2 Azure functions solution that I'm trying to migrate to .NET ore 3.1. I did the following steps:
I changed the project files target framework to netcoreapp3.1
I updated the Nuget packages to the latest stable version
I updated the global.json to
{
"sdk": {
"version": "3.1.100"
}
}
I have no PackageReference to "Microsoft.AspNetCore.App" in the project files
I installed the SDK from https://dotnet.microsoft.com/download/dotnet-core/3.1
I ran pm install -g azure-functions-core-tools#3
Everything went fine but at runtime, I had a serialization issue:
Newtonsoft.Json: Self-referencing loop detected with type 'Platform'. Path '[0].hierarchy.platform'."
I have the 2 DTOs:
public class Platform
{
[JsonRequired]
public string PlatformId { get; set; }
[JsonRequired]
public Guid HierarchyUuid { get; set; }
public Hierarchy Hierarchy { get; set; }
}
public class Hierarchy
{
[JsonRequired]
public string HierarchyId { get; set; }
[JsonIgnore]
public IEnumerable<Platform> Platform { get; set; }
}
I understand the reason of the issue but with .Net Core 2.2 as target framework this DTOs were successfully serialized. As mentioned by Microsoft, in the 3.1 version the serialization has been changed and I guess this is the cause of the issue. I replaced Newtonsoft.Json by System.Text.Json but still had the same issue. Finally, to prevent the circular references between Platform and Hierarchy I kept Newtonsoft.Json and added in the FunctionStartup.Configure method the following:
builder.Services.AddMvcCore().AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
Which needs the Microsoft.AspNetCore.Mvc.NewtonsoftJson package.
When I installed the package version 3.1.1 I got a build error
Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'Microsoft.AspNetCore.Mvc.Core, Version=3.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
Does anybody have an idea why I have this error and how to resolve the issue?

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.

I could not connect to database instance created with Entity Framework generated from model

I created a web application and a model. Then I generated a dbcontext class and a database instance. After I built the project, I tried to connect to that database from Server Explorer in Visual Studio, but could not connect.
I tried to test connection but got an error:
This connection cannot be tested because the specified database does not exist or is not visible to the specified user
Whenever I tried to scaffold view or controller I got this error:
Unable to retrieve metadata for ... one or more validation errors were detected during model generation
ModelsTable is based on type TestModel that has no keys defined.
When I created database object in controller class and write query got same error no key defined.
Also made updates on packages and tried again. I think my connection string is correct.
Here is my model.
public class TestModel
{
[Key]
public string ID { get; } = Guid.NewGuid().ToString();
public string AreaName { get; set; }
public bool IsWorking { get; set; }
public string UserName { get; set; }
public DateTimeOffset Time { get; set; }
}
So I could not use scaffolding, Entity Framework and write query.
Here is my dbcontext class.
public class ModelDB : DbContext
{
public ModelDB()
: base("name=ModelDB")
{
}
public DbSet<TestModel> ModelsTable { get; set; }
}
I searched on internet tried founded solutions but did not understand and could not solve. I hope did not ask unnecessary questions. Thanks for your helping.
Are you using Code First? If so I think you need to generate migrations.
In visual studio go to Package Manager Console and run this commands:
Add-Migration "modelClassName"
Update-Database –Verbose
For more information refer to this link: https://msdn.microsoft.com/en-us/library/jj591621(v=vs.113).aspx
You are missing the set; in the field ID.

asp.net core web api, how to inject the connection string

Here is my asp.net core project structure
1- ASP.NET CORE Web API (contains aspsettings.json)
"ConnectionStrings": {
"DefaultConnection": "Server=(local)\\SQLEXPRESS;Database=testdb;Trusted_Connection=True;"
}
2-SERVICES Project (Web API Call method from Services Project)
3-REPOSITORY Project (Services call method from Repository Project and Repository Project include the DATA Project where all the models are)
4-DATA Project where it's contain all the model with code first
public class TtEntities : DbContext
{
public virtual DbSet<RoomMessage> RoomMessage { get; set; }
public virtual DbSet<UserRoom> UserRoom { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Server=(local)\SQLEXPRESS;Database=testdb;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
....
As you can see, I hardcoded the connection on the method OnConfiguring which is not the best practice for sure.
Is there a way to pass the connection string from the configuration file of the Web API Project?
Is update database command will still work if we pass the connection from the file aspsettings.json from web api project ?
Thanks a lot
A simple solution is like this:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
}
Consider how DefaultConnection is used in line 13. Also a sample appsettings is like as follow:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplication5;"
}
}
DI solves this problem perfectly and .NET Core 2.0 has Microsoft DI thats provides clearly experience with DI.
oh, lets starts(i think that DATA Project and REPOSITORY Project should be one)
from REPOSITORY Project
change your REPOSITORYClass to
public class REPOSITORYClass
{
private readonly TtEntities _db;
public REPOSITORYClass (TtEntities db){
_db = db;
}
//some your staff of REPOSITORYClass thats uses _db
}
now go to SERVICES Project
lets change some service that uses REPOSITORYClass
public class SomeService
{
private readonly REPOSITORYClass _repo;
public SomeService (REPOSITORYClass repo){
_repo = repo;
}
//other staff of SomeService thats uses _repo
}
after that go to ASP.NET CORE Web API startup file and add to
public void ConfigureServices
// Get connection of your repo
string connection = Configuration.GetConnectionString("DefaultConnection");
// add TtEntities as service
services.AddDbContext<TtEntities>(options =>
options.UseSqlServer(connection));
//add your repo
services.AddTransient<REPOSITORYClass>();
//add your service
services.AddTransient<SomeService>();
now go to the contoller thats uses your SomeService
public class SomeController: Controller
{
private readonly SomeService _someService;
public SomeController(SomeService someService){
_someService = someService;
}
//And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
public string SomeMethod()
{
return _someService.SomeMethod();
}
}
And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
thats all
PS also recommend to read this Introduction to Dependency Injection in ASP.NET Core

Resources