How do I build tests using xUnit for an Asp.NetCore WebAPI built with Entity Framework Core and Simple Injector? - asp.net-core

I have created an ASP.NET Core Web API using Entity Framework Core and Simple Injector.
I would like unit tests using xUnit to test my controllers.
I'm not sure where to begin. I believe that I have to mock a container object in my unit tests.
Here is the start up code where the container gets initialized:
public class Startup
{
private Container container;
public IConfiguration Configuration { get; }
private IConfigurationRoot configurationRoot;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
// Build configuration info
configurationRoot = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
InitializeContainer();
services.AddSimpleInjector(container, options =>
{
options.AddAspNetCore()
.AddControllerActivation();
options.AddLogging();
});
}
private void InitializeContainer()
{
container = new SimpleInjector.Container();
container.Options.ResolveUnregisteredConcreteTypes = false;
container.ConfigureServices();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseSimpleInjector(container);
AppSettingsHelper.AppConfig = configurationRoot;
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Here is the code for my services installer:
public static class ServicesInstaller
{
public static void ConfigureServices(this Container container)
{
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
//Assembly.Load will not re-load already loaded Assemblies
container.Register<IFooContext, FooContext>(Lifestyle.Scoped);
container.Register<FooContext>(Lifestyle.Scoped);
}
}
Here is a sample controller:
[Route("[controller]")]
[ApiController]
public class SomeController : ControllerBase
{
private readonly ILogger<SomeController> _logger;
private readonly Container _container;
public SomeController(ILogger<SomeController> p_Logger, Container p_Container)
{
_logger = p_Logger;
_container = p_Container;
}
[HttpGet]
[Route("{p_SomeId}")]
public Some GetOwnerByOwnerId(Guid p_SomeId)
{
Some some;
using (Scope scope = AsyncScopedLifestyle.BeginScope(_container))
{
var dbContext = _container.GetInstance<FooContext>();
some = dbContext.Somes.Where(x => x.SomeId == p_SomeId).FirstOrDefault();
}
return some;
}
}
I'm relatively new to using SimpleInjector.
How would I mock up a container to use for testing?

The controller in the provided example should not be coupled to anything container specific.
Explicitly inject the necessary dependencies into the controller.
[Route("[controller]")]
[ApiController]
public class SomeController : ControllerBase {
private readonly ILogger<SomeController> _logger;
private readonly IFooContext dbContext;
public SomeController(ILogger<SomeController> p_Logger, IFooContext dbContext) {
_logger = p_Logger;
this.dbContext = dbContext;
}
[HttpGet]
[Route("{p_SomeId}")]
public Some GetOwnerByOwnerId(Guid p_SomeId) {
Some some = dbContext.Somes.Where(x => x.SomeId == p_SomeId).FirstOrDefault();
return some;
}
}
Now there is no need to mock the container, which would be seen as an implementation detail code smell.
Mock the dependency abstractions and verify the expected behavior when exercising your unit test(s).
Controllers should also be kept as lean as possible since most other cross-cutting concerns, like making sure the injected context is scoped, are handled by the framework via the configured container at startup.

Related

how to set the output type List<string> in a middleware in .NET Core 2.1?

I have this middleware class when I want to show a List<string> in the output:
namespace WebAspNetCore2_1
{
public class LearningMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<LearningMiddleware> _logger_log;
private readonly List<string> logger;
public LearningMiddleware(RequestDelegate next,ILogger<LearningMiddleware> logger_log)
{
_next = next;
_logger_log = logger_log;
List<string> _logger = new List<string>
{
("EUR/USD"),
("1.0500")
};
logger = _logger;
}
public Task Invoke(HttpContext httpContext)
{
_logger_log.Log(Microsoft.Extensions .Logging.LogLevel.Information,"information of logger",logger[0]);
return _next(httpContext);
}
}
}
I have debugged my code but seen to be correct, my List<> is filled, I don't know why the compiler is throwing this exception:
InvalidOperationException: Could not create an instance of type Microsoft.Extensions.Logging.ILogger`1[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'logger' parameter a non-null default value.
i thought was the order declaration in StartUp, but not
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// app.UseLearningMiddleware();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMiddleware<LearningMiddleware>();
app.UseMvc();
}
link in video for detail evidence: https://youtu.be/2FoLvhLweYo
I tested your code in my side but it worked well... I created a new asp.net core 2.1 MVC project and create a middleware. In StartUp.cs, I put app.UseMiddleware<MyMiddleware>(); just before app.UseMvc(routes =>
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace WebApplication2
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class MyMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<MyMiddleware> _logger_log;
private readonly List<string> logger;
public MyMiddleware(RequestDelegate next, ILogger<MyMiddleware> logger_log)
{
_next = next;
_logger_log = logger_log;
List<string> _logger = new List<string>
{
("EUR/USD"),
("1.0500")
};
logger = _logger;
}
public Task Invoke(HttpContext httpContext)
{
_logger_log.Log(Microsoft.Extensions.Logging.LogLevel.Information, "information of logger", logger[0]);
return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class MyMiddlewareExtensions
{
public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<MyMiddleware>();
}
}
}

.Net Core How to Access Configuration Anywhere in application

I have read through the documentation on the different ways to setup and access configuration in .Net Core 2.1 and also the options pattern that seems to be recommended (https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.1). However, I can't seem to get what I want working:
I have done the following:
AppSettings:
{
"ConnectionStrings": {
"DefaultConnStr": "Server=(localdb)\\MSSQLLocalDB;Database=_CHANGE_ME;Trusted_Connection=True;MultipleActiveResultSets=true;Integrated Security=true",
"AW2012ConnStr": "Server=localhost;Database=AW2012;Trusted_Connection=True;MultipleActiveResultSets=true;Integrated Security=true"
}
}
MyConfig:
public class MyConfig
{
public string AWConnStr { get; }
public string DefaultConnStr { get; }
}
Startup:
public class Startup
{
public IConfiguration _config { get; set; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
_config = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
//add config to services for dependency injection
//services.AddTransient<IMyConfig, MyConfig>();
//services.AddScoped<IMyConfig, MyConfig>();
var section = _config.GetSection("ConnectionStrings");
services.Configure<MyConfig>(section);
}
private static void HandleGetData(IApplicationBuilder app)
{
//DataHelper dataHelper = new DataHelper(_dataHelper);
var _dataHelper = app.ApplicationServices.GetService<DataHelper>();
app.Run(async context =>
{
//await context.Response.WriteAsync("<b>Get Data</b>");
//await context.Response.WriteAsync(dataHelper.GetCompetitions(context.Request.QueryString.ToString()));
await context.Response.WriteAsync(_dataHelper.GetCompetitions(context.Request.QueryString.ToString()));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Map("/Route1", HandleRoute1);
app.Map("/Route2", HandleRoute2);
app.Map("/GetData", HandleGetData);
app.Run(async (context) =>
{
await context.Response.WriteAsync("Non Mapped Default");
});
}
}
I would like to then access the configuration in any class anywhere in my code. So for example I have the following class where I would like to just read the configuration information:
public interface IDataHelper
{
string GetCompetitions(string val);
}
public class DataHelper : IDataHelper
{
private readonly MyConfig _settings;
public DataHelper(IOptions<MyConfig> options)
{
_settings = options.Value;
}
public string GetCompetitions( string queryStringVals)
{
return _settings.AWConnStr;
}
}
As shown above in my Startup class I then want to access/call something in the HandleGetData function in my startup, so that when I browse to the following route: http://localhost:xxxxx/getdata I get back the response from the Something.GetData function.
Is this correct? The problem I'm having is that when I create an instance of class Something, it is requiring me to pass in the configuration object, but doesn't that defeat the purpose of injecting it. How should I be setting this up to work similar to how DBContext gets the context injected with the configuration options. And what's the difference between services.AddTransient and services.AddScoped? I've seen both as a way to register the service.
I would say that in .Net Core application you shouldn't pass instance of IConfiguration to your controllers or other classes. You should use strongly typed settings injected through IOtions<T> instead. Applying it to your case, modify MyConfig class (also property names should match names in config, so you have to rename either config (DefaultConnection->DefaultConnStr, AW2012ConnStr->AWConnStr or properies vice versa):
public class MyConfig
{
public string AWConnStr { get; set; }
public string DefaultConnStr { get; set; }
}
Register it:
public void ConfigureServices(IServiceCollection services)
{
// in case config properties specified at root level of config file
// services.Configure<MyConfig>(Configuration);
// in case there are in some section (seems to be your case)
var section = Configuration.GetSection("ConnectionStrings");
services.Configure<MyConfig>(section);
}
Inject it to required service:
public class MyService
{
private readonly MyConfig _settings;
public MyService(IOptions<MyConfig> options)
{
_settings = options.Value;
}
}
And what's the difference between services.AddTransient and
services.AddScoped? I've seen both as a way to register the service.
Transient lifetime services are created each time they're requested.
Scoped lifetime services are created once per request.
You have to do the same thing for the Something as you did for MyConfig like:
public interface ISomething
{
string GetSomeData();
}
Then:
public class Something : ISomething
{
public IConfiguration _config { get; set; }
public Something(IConfiguration configuration)
{
_config = configuration;
}
public string GetSomeData()
{
return _config["DefaultConnStr"];
}
}
Then in the ConfigureService method of the Startup class as follows:
services.AddScoped<ISomething,Something>();
Then call the GetSomeData() as follows:
public class CallerClass
{
public ISomething _something { get; set; }
public CallerClass(ISomething something)
{
_something = something;
}
public string CallerMethod()
{
return _something.GetSomeData();
}
}
Then:
And what's the difference between services.AddTransient and services.AddScoped? I've seen both as a way to register the service.
Here is the details about this from microsoft:
Service Lifetime details in ASP.NET Core

IConfiguration object is null.

I'm trying to read connection strings from appsettings.json and I'm using:
services.AddSingleton(Configuration);
This line from startup throws null. I'm pretty new to core2.0. Can someone tell what I'm missing?
My startup:
public class Startup
{
public static string ConnectionString { get; private set; }
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton(Configuration);
services.AddSingleton<IConfiguration>(Configuration);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
My controller:
public class CreateController : Controller
{
public IConfiguration _ConnectionString;
public CreateController(IConfiguration configuration)
{
_ConnectionString = configuration;
}
public IEnumerable<string> Get()
{
Markets();
}
public string Markets()
{
using(SqlConnection con = new SqlConnection(_ConnectionString.GetSection("Data").GetSection("ConnectionString").Value))
{
return con.Database;
}
}
}
I've noticed your Startup is missing a constructor. In ASP.NET Core 2, when it calls startup (based on a typical WebHost.CreateDefaultBuilder(args).UseStartup<Startup>() inside a vanilla Program.BuildWebHost) will automatically pass the configuration into the Startup constructor:
public class Startup
{
public IConfiguration Configuration { get; }
// This configuration is automatic, if WebHost.CreateDefaultBuilder(args) is used in Program.cs
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
Just adding that will solve your IConfiguration is null issue.
Now, you should not have to add that Configuration into DI because with the defaults it should already be in there and you can add it as-is to your controller constructor. However, there's no harm in doing so.
Lastly, to join the chorus, using IConfiguration directly in you controllers is not a good idea. Rather look into strongly typed configuration settings. There are tutorials out there that can help - here's the first link I found - but the gist is your controller will end up looking sort of like this:
public class CreateController : Controller
{
public ConnectionStrings _ConnectionStrings;
public CreateController(IOptions<ConnectionStrings> connectionStrings)
{
_ConnectionStrings = connectionStrings.Value;
...
You shouldn't be calling services.AddSingleton(Configuration) in ConfigureServices. It is already in the DI container by default.
You simply need to reference it within your Controler:
public class CreateController : Controller
{
public IConfiguration _configuration;
public CreateController(IConfiguration configuration)
{
_configuration = configuration;
}
public IEnumerable<string> Get()
{
Markets();
}
public string Markets()
{
var connectionString = _configuration.GetConnectionString("ConnectionStringName");
using( SqlConnection con = new SqlConnection(connectionString) )
{
return con.Database;
}
}
}
It is null because it hasn't been set. You need to build your configuration first which is best done in the constructor. As others have pointed out it is not recommended to do this.
Example
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
builder.AddUserSecrets<Startup>();
}
Configuration = builder.Build();
}
private IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(Config);
}
}

XUnit DI through overridden Startup file (.net core)

I have build a WebAPI and apart from my tests running on Postman I would like to implement some Integration/Unit tests.
Now my business logic is very thin, most of the time its more of CRUD actions, therefore I wanted to start with testing my Controllers.
I have a basic setup. Repository pattern (interfaces), Services (business logic) and Controllers.
The flow goes Controller (DI Service) -> Service (DI Repo) -> Repo Action!
So what I did was override my Startup file to change into a in memory database and the rest should be fine (I would assume) Services are added, repos are added and now I am pointing into a in memory DB which is fine for my basic testing.
namespace API.UnitTests
{
public class TestStartup : Startup
{
public TestStartup(IHostingEnvironment env)
: base(env)
{
}
public void ConfigureTestServices(IServiceCollection services)
{
base.ConfigureServices(services);
//services.Replace<IService, IMockedService>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
base.Configure(app, env, loggerFactory);
}
public override void SetUpDataBase(IServiceCollection services)
{
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = ":memory:" };
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);
services
.AddEntityFrameworkSqlite()
.AddDbContext<ApplicationDbContext>(
options => options.UseSqlite(connection)
);
}
}
}
I wrote my first test, but the DatasourceService is not there:
The following constructor parameters did not have matching fixture data: DatasourceService datasourceService
namespace API.UnitTests
{
public class DatasourceControllerTest
{
private readonly DatasourceService _datasourceService;
public DatasourceControllerTest(DatasourceService datasourceService)
{
_datasourceService = datasourceService;
}
[Xunit.Theory,
InlineData(1)]
public void GetAll(int companyFk) {
Assert.NotEmpty(_datasourceService.GetAll(companyFk));
}
}
}
What am I missing?
You can't use dependency injection on test classes. You can only let xunit inject special fixtures via constructor (see docs).
For Integration Testing you want to use the TestServer class from Microsoft.AspNetCore.TestHost package and a separate Startup.cs class (easier to setup configuration than inheritance imho).
public class TestStartup : Startup
{
public TestStartup(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; }
public void ConfigureTestServices(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Scoped<IService, MockedService>());
services.AddEntityFrameworkSqlite()
.AddDbContext<ApplicationDbContext>(
options => options.UseSqlite(connection)
);
}
public void Configure(IApplicationBuilder app)
{
// your usual registrations there
}
}
In your unit test project, you need to create an instance of the TestServer and perform the test.
public class DatasourceControllerTest
{
private readonly TestServer _server;
private readonly HttpClient _client;
public DatasourceControllerTest()
{
// Arrange
_server = new TestServer(new WebHostBuilder()
.UseStartup<TestStartup>());
_client = _server.CreateClient();
}
[Xunit.Theory,
InlineData(1)]
public async Task GetAll(int companyFk) {
// Act
var response = await _client.GetAsync($"/api/datasource/{companyFk}");
// expected result from rest service
var expected = #"[{""data"":""value1"", ""data2"":""value2""}]";
// Assert
// This makes sure, you return a success http code back in case of 4xx status codes
// or exceptions (5xx codes) it throws an exception
response.EnsureSuccessStatusCode();
var resultString = await response.Content.ReadAsStringAsync();
Assert.Equals(resultString, expectedString);
}
}
Now, when you call operations which write to the database, you can also check if the data is really written to the database:
[Xunit.Theory,
InlineData(1)]
public async Task GetAll(int companyFk) {
// Act
var response = await _client.DeleteAsync($"/api/datasource/{companyFk}");
// expected result from rest service
// Assert
response.EnsureSuccessStatusCode();
// now check if its really gone in the database. For this you need an instance
// of the in memory Sqlite DB. TestServer has a property Host, which is an IWebHost
// and it has a property Services which is the IoC container
var provider = _server.Host.Services;
var dbContext = provider.GetRequiredService<ApplicationDbContext>();
var result = await dbContext.YourTable.Where(entity => entity.Id == companyFk).Any();
// if it was deleted, the query should result in false
Assert.False(result);
}
Now you can use Xunit.DependencyInjection in your tests.
namespace Your.Test.Project
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IDependency, DependencyClass>();
}
}
}
your DI-classes:
public interface IDependency
{
int Value { get; }
}
internal class DependencyClass : IDependency
{
public int Value => 1;
}
and XUnit-test:
public class MyAwesomeTests
{
private readonly IDependency _d;
public MyAwesomeTests(IDependency d) => _d = d;
[Fact]
public void AssertThatWeDoStuff()
{
Assert.Equal(1, _d.Value);
}
}

.Net Core passing connection string to DBContext class

Just started using .Net Core and facing passing connection string information to Context console project.
I have 4 projects, created using .Net Core.
MVC
Service Layer
Domain Layer
Data Layer
In MVC project, I have Startup.cs file where i am reading appsettings.json file
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddMvc();
// Add appsettings
services.Configure<AppSettingsConfig>(Configuration.GetSection("AppSettings"));
}
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();
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
In my 4th project (Data Layer), which Console Project and having following DBContext class. This project doesn't have Startup.cs as i MVC project having. Not created by default by VS 2015.
public class MyDWContext : DbContext
{
public MyDWContext() : base ()
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Data Source=localhost;Initial Catalog=MyDW; Persist Security Info = False; User ID = TempUser; Password = Temp123");
}
public DbSet<User> Users { get; set; }
public DbSet<Class> Classs { get; set; }
}
I have been to other post as well but i believe its created using older version or RC version. So some time i cannot find correct object or .Net classes.
As i have connection string is in MVC project, how can i use connection string during my MVC call to Data layer.
I have Web.API (Core) project as well and that having own connection string (different user configuration in connection string which having only read access). How can i use Web2.API connection string when i am making call from Web2.API project.
Instead of passing connection string to DbContext, configuring DbContext in Startup.cs(if possible) is better way. See official docs to understand how to configure DbContext and use it via Dependency Injection.
EDIT : Below code is not good way
However, if you want to pass connection string to DbContext you can use options pattern.
Here is an example how to pass connection string with options pattern:
First you need an options class which accessible from Data Layer and MVC layer
public class ConnectionStringOption
{
public string ConStr { get ; set; }
}
Then set option value
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<ConnectionStringOption>(options=>
{
// set connection string from configuration
options.ConStr = Configuration.GetConnectionString("Default");
});
}
appsetting.json
{
"ConnectionStrings": {
"Default": "<your connection string>"
}
}
Finally DbContext
private readonly IOptions<ConnectionStringOption> _conStrOptions;
protected YourDbContext()
{
}
public YourDbContext(IOptions<ConnectionStringOption> conStrOptions, DbContextOptions options)
: base(options)
{
_conStrOptions= conStrOptions;
}
Edit for another way
Using Static Service Locator may be a solution:
Create a DependencyResolver in Data Layer
public static class DependencyResolver
{
private static IServiceProvider _provider;
public static IServiceProvider ServiceProvider
{
get
{
return _provider;
}
set
{
if(_provider == null)
{
_provider = value;
}
}
}
}
In ConfigureServices method
public void ConfigureServices(IServiceCollection services)
{
// other stuff
services.AddOptions();
services.Configure<ConnectionStringOption>(options=>
{
// set connection string from configuration
options.ConStr = Configuration.GetConnectionString("Default");
});
DependencyResolver.ServiceProvider = services.BuildServiceProvider();
}
And finally get option:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var conStr = DependencyResolver.ServiceLocator.GetService<IOptions<ConnectionStringOption>>().Value.ConStr;
optionsBuilder.UseSqlServer();
}
Final Edit for previous stupid way
public static class ConnectionStringGetter
{
public static string ConStr{get;set;}
}
public Startup(IHostingEnvironment env)
{
//...
Configuration = builder.Build();
ConnectionStringGetter.ConStr = Configuration.GetConnectionString("Default");
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConnectionStringGetter.ConStr);
}