Add an implementation of 'IDesignTimeDbContextFactory<ApplicationDbContext>' to the project - asp.net

I Created an asp.net core project And I selected UseIndiviualUserAccount As My AutenticationType,
After preparing project by visual studio i got some prebuilt class and controller,
Obviously i got migration folder and its config since i dont want to use defulat structure of asp.net core ,i deleted the migration folder and i created a new class library and i Rename it to MyProject.Core.
in MyProject.Core Class Library i create my db models and dbContext classes,so i need to run the add-migration "init" command for creating my database so i did but i got below error,
Note : i am running the add migration command in Myproject.Core in PMC !!
Unable to create an object of type 'ApplicationDbContext'. Add an implementation of 'IDesignTimeDbContextFactory' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
how can i fix this error, i read some article in current site and the other website but i cant fix my problem.
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IUnitOfWork, UnitOfWork>();
services.AddTransient<IProvinceRepository, ProvinceRepository>();
services.AddTransient<IBrandRepository, BrandRepository>();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser,ApplicationRole,string>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options): base(options)
{
}
static ApplicationDbContext()
{
// Set the database intializer which is run once during application start
// This seeds the database with admin user credentials and admin role
// Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}

This can happen when EF don't know where the entry point to your application is. You do not need to implement IDesignTimeDbContextFactory if you're using BuildWebHost.
First of all, make sure that you are running your migration from the project containing the migrations.
Eg... if you're using Package Manager Console:
cd .\MyProject.Core
Then run your migration using startup-project and point it to the project with BuildWebHost.
dotnet ef --startup-project ../MyProject.Web/ migrations add Initial
Otherwise EF will not know where your implementation is.

Related

How to read the Azure App Configuration in Service Fabric ASP.NET Core Stateless Web API?

I need help to read the App Configuration in Service Fabric ASP.NET Core Stateless Web API. In the Normal ASP.NET Core Web API, we can use the Host CreateDefaultBuilder to read the config and use it in the Startup and other classes. If I try to inject in the Service Fabric Web API, it does not work. The Program.cs contains only the following.
private static void Main(string[] args)
{
try
{
// The ServiceManifest.XML file defines one or more service type names.
// Registering a service maps a service type name to a .NET type.
// When Service Fabric creates an instance of this service type,
// an instance of the class is created in this host process.
ServiceRuntime.RegisterServiceAsync("EmailAPIType",
context => new EmailAPI(context)).GetAwaiter().GetResult();
ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(EmailAPI).Name);
// Prevents this host process from terminating so services keeps running.
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
throw;
}
}
And the startup.cs contains
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace EmailAPI
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
I tried to inject Host CreateDefaultBuilder in program.cs
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.ConfigureAppConfiguration((hostingContext, config) =>
{
var settings = config.Build();
config.AddAzureAppConfiguration(options =>
{
options.Connect(ConnectionString)
.Select(ConfigValues).TrimKeyPrefix(qualtricsAppConfigPrefix + ":")
.UseFeatureFlags();
});
})
.UseStartup<Startup>());
I am running out of Ideas how to do. In Azure Function App we can do it in Startup, not sure how we can handle in Service Fabric ASP.NET Core Web API. Any examples please.
I have uploaded the sample project created in One Drive. Here is the link to it.
https://1drv.ms/u/s!Au2rKbF-hqWY61pykRlWRTI4DB8t?e=vz0c8z
Finally figured it out. For anyone who is interested here is it. If you have any better way to do it please let me know
public class Startup
{
private static string prefix = "";
public Startup(IConfiguration configuration)
{
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json", false, false)
.AddEnvironmentVariables();
var builder = configurationBuilder.Build();
configurationBuilder.AddAzureAppConfiguration(o => AddApplicationKeysAppConfiguration(o, builder));
builder = configurationBuilder.Build();
configuration = builder;
Configuration = configuration;
}
private static void AddApplicationKeysAppConfiguration(AzureAppConfigurationOptions options, IConfigurationRoot configuration)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
environment = string.IsNullOrWhiteSpace(environment) ? Environment.GetEnvironmentVariable("Environment") : environment;
string connectionString = "";
options.Connect(connectionString)
.Select($"{prefix}*", environment).TrimKeyPrefix(prefix + ":")
.UseFeatureFlags(flagOptions =>
{
flagOptions.Label = environment;
});
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

Read docker-compose environment variable from ASP.NET Core controller

I am trying to dockerize an ASP.NET Core 5 Web API project and so I am going to transfer all configs from appSettings.json to docker-compose environment section. And then going to read them from environment section in a controller. How should do this?
I have tried to use IConfiguration and Environment in the controller, but I have just got Null.
My Program.cs is:
namespace Order.Api
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
}
}
And the StartUp.cs is:
namespace Order.Api
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<OrderContext>(options =>
options.UseSqlServer(Configuration.GetValue<string>("ConnectionString")));
// options.UseSqlServer(Configuration.GetConnectionString("ConnectionString")));
services.AddControllers();
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Order.Api", Version = "v1"}); });
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Order.Api v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}
}
And the docker-compose.override is:
version: '3.4'
services:
Order.Api :
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sqldata;Database=Order;User Id=sa;Password=Pass#word}
- MyConfig=Active
ports:
- "5001:80"
sqldata :
environment:
- SA_PASSWORD=Pass#word
- ACCEPT_EULA=Y
ports:
- "5433:1433"
volumes:
- order-sqldata:/var/opt/mssql
volumes:
order-sqldata:
external: false
ASP.NET Core provides an ability to load configuration from different places:
appsettings.json
appsetting.<EnvName>.json
environment variables
user secrets
command line arguments
You shouldn't worry about where the settings came from. It's the same from developer's perspective. You can imagine it as a bunch of layer (each next layer overrides a setting from previous one). For example. When your application starts it tries to default load settings from appsettings.json, then override it by settings from appsetting.<EnvName>.json, then from environment variables, etc.
So, when you try to override ConnectionString in environment variables, the first thing you need to check it appsettings.json. How is it defined there? Let's creates simplest configuration:
{
"ConnectionStrings": {
"ConnectionString": "from config"
},
"MyConfig": {
"Key": "from config"
}
}
To read this connection in Startup.cs, you don't need to change anything. Use your options.UseSqlServer(Configuration.GetConnectionString("ConnectionString")));.
And to override it in environment variables you need to provide it with specific name: ConnectionStrings__ConnectionString=<new_connection>. It's pretty simple, you need to flatten your JSON configuration and use __ (double underscore) as a separator.
For custom configuration (like MyConfig) you need to do a little bit more. You need to create options class, like:
public class MyConfigOption
{
public string Key { get; set; }
}
and configure it in Startup.cs:
services.Configure<MyConfigOption>(Configuration.GetSection("MyConfig"));
and then you will be able to override it in environment variables MyConfig__Key=value.
To use it in your controller, you need to ask DI for this options:
public Controller(IOptions<MyConfigOption> options)
{
this.options = options;
}
options will contain your configuration.
See Docs for more details.

The name "Configuration" does not exist in the current context

When trying to register a database context in startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(option => option.EnableEndpointRouting = false);
services.AddDbContext<PostDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("PostDbContext")));
}
I get error
The name "Configuration" does not exist in the current context.
All code examples are taken from the official Microsoft documentation.
Tutorials -> MVC -> Get started -> Add model.
ASP.NET Core version: 3.1
How fix it?
I have not defined a configuration.
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
This problem occurs because you have not defined Configuration which is an instance of IConfiguration interface like this-
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
Here Configuration is important to define which checks configuration details.
For Ex.-Configuration.GetConnectionString("Your Connection String") checks the connection string from appsettings.json file to get or set data in database.

How to implement dependency injection in an MSTest project using Startup.cs and Assembly

In our application, I have used Visual Studio 2017 .NET Core 2. I have implemented dependency injection in a Web project Startup.cs class. I have to implement the same in a new test project. How can I inject dependencies of repositories in the test project?
Please see the below code snippet
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using NLog.Web;
namespace Kpmg.Kdat.Data.Services.Directory.Tests
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseNLog()
.Build();
}
}
The purpose of the above code is to inject dependencies. In Startup.cs I have configured all the dependencies.
While using the above code I am getting the below error:
Error CS0017 Program has more than one entry point defined. Compile with /main to specify the type that contains
the entry point.
How can I fix the issue?
Why do you want to include the above in your unit test project? Generally, you shouldn't have to.
If you want mock dependencies, in your unit test project you can do something like this.
public class TestServiceModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(ctx =>
{
// Return mock implementation of IMyService
}).As<IMyService>()
.SingleInstance();
// Register your mock services like above
}
}
And use like,
[TestInitialize]
public void Initialize()
{
var builder = new ContainerBuilder();
builder.RegisterModule<TestServiceModule>();
}
Now you can use IMyService.

Unable to resolve service for type 'MyApp.ApplicationDbContext' while attempting to activate

I am having issue after integrated in an existing ASP.Net core 2.0 application a newly created authentication project items based on ASP.Net Core 2.0 too.
after some adjustments then successful build, in the browsser I got the next error:
An unhandled exception occurred while processing the request.
InvalidOperationException: Unable to resolve service for type 'SpaServices.ApplicationDbContext' while attempting to activate
The authentication has to use a separate database which is not yet scaffolded
My Startup.cs is as follows:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/Account/Manage");
options.Conventions.AuthorizePage("/Account/Logout");
});
// Register no-op EmailSender used by account confirmation and password reset during development
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=532713
services.AddSingleton<IEmailSender, EmailSender>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
#region webpack-middleware-registration
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
// Call UseWebpackDevMiddleware before UseStaticFiles
app.UseStaticFiles();
#endregion
#region mvc-routing-table
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
#endregion
}
And my constructor is as below:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
I have updated the constructor to explicitly expect a type the container knows how to resolve:
public ApplicationDbContext(DbContextOptions options)
: base(options)
{
}
Without success, any thoughts ?
You need to include the following in your ConfigureServices() method:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("[Your Connection String Identifier]")));
Currently, you have only added a "SchoolContext" DbContext

Resources