How get register dbcontext in startup class for reference? - entity-framework

I configure my DbContext with dependency injection in Startup, actually i need send my registered dbcontext to my class handler (EventBusExtension.GetHandlers()) but i dont know how get directly the context registered:
public void ConfigureServices(IServiceCollection services)
{
...
var dbContextOptions = new DbContextOptionsBuilder<cataDBContext>()
.UseSqlServer(Configuration.GetConnectionString("SqlServerConnect"))
.Options;
//*****************************************************************************
services.AddSingleton(dbContextOptions);
// Finally register the DbContextOptions:
services.AddSingleton<cataDBContextOptions>();
// This Factory is used to create the DbContext from the custom DbContextOptions:
services.AddSingleton<IContextDBFactory, ContextDBFactory>();
// Finally Add the Applications DbContext:
services.AddDbContext<cataDBContext>();
services.AddEventBusHandling(EventBusExtension.GetHandlers(Configuration));
...
}
How i can get and send the context to EventBusExtension.GetHandlers() ?

For how to get the instance in the Startup,you could use the following code:
//1.Register the service
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("YourConnnectionString")));
//2.Build an intermediate service provider
var sp = services.BuildServiceProvider();
//3.Resolve the services from the service provider
var myDbContext = sp.GetService<MyDbContext>();
//4.then you could pass the myDbContext to the EventBusExtension.GetHandlers()

The accepted anser works but as mentioned in comments and this microsoft document ASP0000 calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created.
Calling BuildServiceProvider creates a second container, which can create torn singletons and cause references to object graphs across multiple containers.
A correct way to get LoginPath is to use the options pattern's built-in support for DI.
For example to use your dbContext to get all active Host URLs to apply in CORs instead of using services.AddCors(.... you can use this code :
services.AddOptions<CorsOptions>()
.Configure<ApplicationDbContext>(
(options, db) =>
{
options.AddPolicy("AllowOrigin", builder =>
builder.WithOrigins(db.Set<MyHostsEntity>().Where(e => e.IsActive).Select(e => e.Url).ToArray())
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
}
);

Related

How Do I Create a DbContextFactory Within a Blazor Background Service?

I am working on my first Blazor Server application, which is also my first Entity Framework Core application. I am wanting to set up a background service which, once a day in the early morning, checks the database to see if any of a certain record type has been added with yesterday's date. If so, the relevant records are pulled, formatted, and then emailed to a stakeholder.
I have the EF, formatting, and emailing code working just fine when I trigger the report by manually visiting the page. The problem that I have is how to provide the background service with a DbContextFactory so that the EF and related code can execute.
Up to this point I've always used Razor-based dependency injection to inject the IDbContextFactory via an inject IDbContextFactory<OurAppContext> DbFactory at the top of the page, and then accessed the DbFactory via the DbFactory variable.
However, background services are (according to this Microsoft tutorial) set up through Program.cs, so I don't have access to Razor-based dependency injection there.
I have set up my background service (what I call the PhaseChangeReportService) as indicated in the above link, and it dutifully outputs to the console every 10 seconds that it is running with an updated execution count. I don't fully understand what's going on with the various layers of indirection, but it appears to be working as Microsoft intended.
I noted that the constructor for the background service takes in an ILogger as a parameter, specifically:
namespace miniDARTS.ScopedService
{
public sealed class PhaseChangeReportService : IScopedProcessingService
{
private int _executionCount;
private readonly ILogger<PhaseChangeReportService> _logger;
public PhaseChangeReportService(ILogger<PhaseChangeReportService> logger)
{
_logger = logger;
}
public async Task DoWorkAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
++_executionCount;
_logger.LogInformation("{ServiceName} working, execution count: {Count}", nameof(PhaseChangeReportService), _executionCount);
await Task.Delay(10_000, stoppingToken);
}
}
}
}
I was (and am) confused that the constructor is never referenced within Visual Studio, but when I drop a breakpoint on its one line of code it is hit. I tried modifying this constructor's signature so that it took in an IDbFactory<OurAppContext> as well, so that whatever dark magic is allowing an ILogger<BackgroundServiceType> to come in for assignment to _logger might bring in a DbFactory<OurAppContext> as well, like so:
private readonly ILogger<PhaseChangeReportService> _logger;
private readonly IDbContextFactory<miniDARTSContext> _dbContextFactory;
public PhaseChangeReportService(ILogger<PhaseChangeReportService> logger, IDbContextFactory<miniDARTSContext> dbContextFactory)
{
_logger = logger;
_dbContextFactory = dbContextFactory;
}
However, doing so just led to the constructor breakpoint being skipped over and not breaking, with no exception being thrown or any console output of any kind (i.e. the prior execution count console output no longer showed up). So, I gave up on that approach.
Here is the relevant section of Program.cs:
// Configure the database connection.
string connectionString = builder.Configuration.GetConnectionString("miniDARTSContext");
var serverVersion = new MySqlServerVersion(new Version(8, 0, 28));
builder.Services.AddDbContextFactory<miniDARTSContext>(options => options.UseMySql(connectionString, serverVersion), ServiceLifetime.Scoped);
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<ScopedBackgroundService>();
services.AddScoped<IScopedProcessingService, PhaseChangeReportService>();
})
.Build();
host.RunAsync();
Here's IScopedProcessingService.cs:
namespace miniDARTS.ScopedService
{
public interface IScopedProcessingService
{
Task DoWorkAsync(CancellationToken stoppingToken);
}
}
And here's ScopedBackgroundService.cs:
namespace miniDARTS.ScopedService;
public sealed class ScopedBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<ScopedBackgroundService> _logger;
public ScopedBackgroundService(IServiceProvider serviceProvider, ILogger<ScopedBackgroundService> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"{nameof(ScopedBackgroundService)} is running.");
await DoWorkAsync(stoppingToken);
}
private async Task DoWorkAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"{nameof(ScopedBackgroundService)} is working.");
using (IServiceScope scope = _serviceProvider.CreateScope())
{
IScopedProcessingService scopedProcessingService = scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();
await scopedProcessingService.DoWorkAsync(stoppingToken);
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"{nameof(ScopedBackgroundService)} is stopping.");
await base.StopAsync(stoppingToken);
}
}
I'm confident I'm misunderstanding something relatively fundamental here when it comes to services / dependency injection, but my Googling and review of past StackOverflow answers has not turned up anything I can run with.
The IDbContextFactory is an interface that is used for creating instances of a DbContext. When you add it to your services on program.cs for Blazor (services.AddDbContextFactory(parameters)), it implements the IDbContextFactory for you. This allows you to use the #inject IDbContextFactory<YourDbContext> DbFactory at the top of your razor components and then within your code you can call the CreateDbContext method when you need to create an instance of the DbContext (ex. using var context = DbFactory.CreateDbContext()).
You can pass an injected DbContextFactory as a parameter from a razor component to a class, and then use that DbContextFactory in a method to create an instance of the DbContext (see constructor injection), but that still relies on the razor component to inject the DbContextFactory to begin with.
To create an instance of a DbContext independent of a razor component, you need to use the constructor for your DbContext. Your DbContext will have a public constructor with a DbContextOptions parameter (this is required to be able to use AddDbContextFactory when registering the factory service in program.cs). You can use this constructor to implement your own factory. If you aren't sure which options to use, you can check your program.cs to see what options you used there.
public class YourDbFactory : IDbContextFactory<YourDbContext>
{
public YourDbContext CreateDbContext()
{
var optionsBuilder = new DbContextOptionsBuilder<YourDbContext>();
optionsBuilder.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=Test"));
return new YourDbContext(optionsBuilder);
}
}
Once you've created your own implementation of the IDbContextFactory interface, you can then use it in your code independent of razor components - for example in the background service class.
YourDbFactory DbFactory = new YourDbFactory();
using var context = DbFactory.CreateDbContext();

EF Core Migrations in Azure Function startup

According to https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection the service provider should not be used until AFTER the startup has completed running. Indeed, if I try to get a registered service it will fail.
Example:
[assembly: FunctionsStartup(typeof(Startup))]
namespace Fx {
public sealed class Startup : FunctionsStartup {
public override void Configure(IFunctionsHostBuilder builder) {
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
builder.Services.AddInfrastructure(configuration);
builder.Services.AddApplication();
var serviceProvider = builder.Services.BuildServiceProvider();
DependencyInjection.AddDatabase(serviceProvider).GetAwaiter().GetResult();
}
}
}
public static class DependencyInjection {
public static async Task AddDatabase(IServiceProvider services) {
using var scope = services.CreateScope();
var serviceProvider = scope.ServiceProvider;
var context = serviceProvider.GetRequiredService<ApplicationDbContext>();
//Error generated here
if (context.Database.IsSqlServer()) {
await context.Database.MigrateAsync();
}
await ApplicationDbContextSeed.SeedSamplePersonnelDataAsync(context);
}
public static IServiceCollection AddInfrastructure(
this IServiceCollection services,
IConfiguration configuration) {
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());
return services;
}
}
This produces the following error
Microsoft.EntityFrameworkCore: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
Is there a good option for migrating and seeding during startup?
The easiest way I found to run code after startup was by registering a custom IWebJobsStartup by using the WebJobsStartupAttribute (the FunctionsStartupAttribute actually also inherits from this attribute). In the WebJobsStartup class you'll need to register your extension using the AddExtension where you are able to use dependency injection and seed your database. My code:
[assembly: WebJobsStartup(typeof(DbInitializationService), "DbSeeder")]
namespace Our.Database.Seeder
{
public class DbInitializationService : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
builder.AddExtension<DbSeedConfigProvider>();
}
}
[Extension("DbSeed")]
internal class DbSeedConfigProvider : IExtensionConfigProvider
{
private readonly IServiceScopeFactory _scopeFactory;
public DbSeedConfigProvider(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public void Initialize(ExtensionConfigContext context)
{
using var scope = _scopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetService<YourDbContext>();
dbContext.Database.EnsureCreated();
// Further DB seeding, etc.
}
}
}
According to your code, I assume that you're building something aligned to the CleanArchitecture Repository on Github. https://github.com/jasontaylordev/CleanArchitecture
The main difference between this repo and your apporach, is that you're obviously not using ASP.NET, which is not a problem at all, but requires a little bit more configuration work.
The article already mentioned (https://markheath.net/post/ef-core-di-azure-functions) refers another blogpost (https://dev.to/azure/using-entity-framework-with-azure-functions-50aa), which briefly explains that EntityFramework Migrations are not capable of auto-discovering your migrations in an Azure Function. Therefore, you need to implement an instance of IDesignTimeDbContextFactory. I also stumbled upon it in the microsoft docs:
https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli#from-a-design-time-factory
You could for example place it inside your Infrastructure\Persistence\Configurations folder. (Once again, I'm only assuming that you're following the CleanArchitecture repo structure)
DI in AZURE Functions
Caveats
A series of registration steps run before and after the runtime processes the startup class. Therefore, keep in mind the following items:
The startup class is meant for only setup and registration. Avoid using services registered at startup during the startup process. For instance, don't try to log a message in a logger that is being registered during startup. This point of the registration process is too early for your services to be available for use. After the Configure method is run, the Functions runtime continues to register additional dependencies, which can affect how your services operate.
The dependency injection container only holds explicitly registered types. The only services available as injectable types are what are setup in the Configure method. As a result, Functions-specific types like BindingContext and ExecutionContext aren't available during setup or as injectable types

Get generated SQL for a DbContext.SaveChanges in Entity Framework Core

In Entity Framework Core, is it possible to see the SQL that will be applied when the SaveChanges() method is called on the DbContext?
EF Core 5.0+
There are a simple builtin solution, add the following function to the DbContext class.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine);
this will log both queries and commands.
See here for mote details: Simple Logging
Here are the docs on creating a LoggerFactory in Core 3. In short:
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
You may need to add a reference to Microsoft.Extensions.Logging.Console.
Use the DbContextOptionsBuilder to enable logging for a context.
optionsBuilder.UseLoggerFactory(loggerFactory)
I'll repeat the warning from here:
It is very important that applications do not create a new ILoggerFactory instance for each context instance. Doing so will result in a memory leak and poor performance.
Therefore, they recommend using a singleton/global instance:
public static readonly ILoggerFactory MyLoggerFactory =
LoggerFactory.Create(builder => { builder.AddConsole(); });
you can use console logger "EF Core logging automatically integrates with the logging mechanisms of .NET Core "
you can read about here :
https://www.entityframeworktutorial.net/efcore/logging-in-entityframework-core.aspx
You can use DbContextOptionsBuilder.UseLoggerFactory(loggerFactory) method to log all sql output.By using constructor Injection like below
public class DemoContext : ObjContext
{
private readonly ILoggerFactory _loggerFactory;
public DemoContext() { }
public DemoContext(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseLoggerFactory(_loggerFactory);
}
}
using (var context = new DemoContext(_loggerFactory))
{
var Employees = context.Employee.ToList();
}
Or
I suggest a few other ways of viewing the SQL generated is to use reflection to create an ObjectQuery object and then call the ToTraceString() method to actually store the query results.
using (var context = new EntityContext())
{
var query = context.Customers.Where(c => c.Id == 1);
var sql = ((System.Data.Objects.ObjectQuery)query).ToTraceString();
}
Use SQL Logging
Using The DbContext.Database.Log property can be set to a delegate for any method that takes a string.
Log SQL to the Console.
using (var context = new EntityContext())
{
context.Database.Log = Console.Write;
}
Log SQL to Visual Studio Output panel.
using (var context = new EntityContext())
{
context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
}
It's a bit tricky to log EF Core's SQL in an ASP.NET MVC web app. Unlike Entity Framework, EF Core lacks the easy-to-use DBContext.Database.Log property. As #DharmaTurtle mentioned, you can use LoggerFactory.Create, and this can work, but it does create a separate ILoggerFactory than the one that the rest of the app uses for logging (one that is apparently not using appsettings.json for options.)
The following approach is required if you want to use the same log factory for DBContext that the rest of the ASP.NET MVC web app uses:
Create a derived class of DbContext (or, if this was already done, modify the existing class appropriately). Note: this example will only log SQL in Debug builds, not Release builds.
public class DbContextWithLogging : Microsoft.EntityFrameworkCore.DbContext
{
ILoggerFactory _loggerFactory;
IConfiguration _configuration; // Provides access to appsettings.json
public DbContextWithLogging(ILoggerFactory loggerFactory, IConfiguration configuration)
=> (_loggerFactory, _configuration) = (loggerFactory, configuration);
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
#if DEBUG
builder.UseLoggerFactory(_loggerFactory);
// This line causes parameter values to be logged:
builder.EnableSensitiveDataLogging();
#endif
}
}
Note: this approach is not compatible with calling AddDbContext in Startup.ConfigureServices, so if there is already a call to AddDbContext, disable/remove it. In my case, the existing derived class of DbContext had a constructor that accepted (DbContextOptions<BarreleyeDbContext> options), which I removed.
In your Startup.ConfigureServices method, configure logging (e.g. to print to console) and enable the custom DbContext:
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging((ILoggingBuilder builder) => {
builder.AddConsole();
});
// In ASP.NET Core apps, a Scope is created around each server request.
// So AddScoped<X, Y>() will recreate class Y for each HTTP request.
services.AddScoped<DbContext, DbContextWithLogging>();
... // leave the rest as before
}
Whatever uses DbContext (e.g. controllers, or 'repositories' in the Repository pattern) should obtain it automagically via constructor injection.
EF Core uses LogLevel.Information when printing the SQL, so you need the Information level to be enabled. If you look at your appsettings.json file, you'll want to see something like this:
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
In particular, EF Core log filtering can be controlled with a key like
"Microsoft.EntityFrameworkCore": "Information",
but if this key is missing, the "Microsoft" key is used instead.
This might not work! Look for a second file called appsettings.Development.json - watch out, Visual Studio might hide this file "inside" appsettings.json. If appsettings.Development.json exists, its contents override appsettings.json (at the granularity of individual keys).
Once it's working, you'll see log info that looks like this (yes, SELECT statements are logged as well as INSERT, UPDATE and DELETE):
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (0ms) [Parameters=[#__p_0='297'], CommandType='Text', CommandTimeout='30']
SELECT e.id, e.config, e.end_date, e.entity_name, e.entity_type, e.location, e.start_date
FROM entities AS e
WHERE e.id = #__p_0
LIMIT 1

Customizing Autofac in Azure mobile app results in 'No service registered for ITableControllerConfigProvider type' exception

I'm trying to customize an Azure Web app application that was created with Visual Studio. I've added an AccountsController to help with user registration using the Owin membership tables. I want to add Owin to the site, so I'm customizing the WebApiConfig.cs file with this method:
public static void Register(HttpConfiguration config)
{
// Use this class to set configuration options for your mobile service
var options = new ConfigOptions();
var configBuilder = new ConfigBuilder(options, (configuration, builder) =>
{
var executingAssembly = Assembly.GetExecutingAssembly();
var file = FileHelper.GetLoggingConfigFile(executingAssembly);
// startup the logging
_logger = new Logger(MethodBase.GetCurrentMethod().DeclaringType, file);
//builder.RegisterInstance(new CustomOwinAppBuilder(configuration))
// .As<IOwinAppBuilder>();
//configure the Autofac IoC container
AutofacBuilder.Configure(executingAssembly, _logger, builder, new MvcModule(),
new TaskModule());
});
var defaultConfig = ServiceConfig.Initialize(configBuilder);
// Make sure this is after ServiceConfig.Initialize
// Otherwise ServiceConfig.Initialize will overwrite your changes
StartupOwinAppBuilder.Initialize(app =>
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(TrainMobileContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// app.UseFacebookAuthentication("", "");
});
defaultConfig.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// To display errors in the browser during development, uncomment the following
// line. Comment it out again when you deploy your service for production use.
// config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
Database.SetInitializer(new MobileServiceInitializer());
}
The AutofacBuilder handles a lot of the registration with statements like so:
builder.RegisterType<RepositoryProvider>().As<IRepositoryProvider>().InstancePerHttpRequest();
builder.RegisterType<DataManager>().As<IDataManager>().InstancePerHttpRequest();
builder.RegisterType<Logger>().As<ILogger>().InstancePerLifetimeScope();
// new TrainMobileUserStore(context.Get<SpaceLinxContext>())
builder.RegisterControllers(assembly).InstancePerHttpRequest();
builder.RegisterApiControllers(assembly);
builder.RegisterModelBinders(assembly).InstancePerHttpRequest();
builder.RegisterType<LogAttribute>().PropertiesAutowired();
builder.RegisterFilterProvider();
// Needed to allow property injection in custom action filters.
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(assembly).InjectActionInvoker();
When I've made these changes however, two things happen:
Firstly, the default azure mobile app default helper page disappears and I get a default page with this:
HTTP Error 403.14 - Forbidden
The Web server is configured to not list the contents of this directory.
Secondly, when I attempt to call the Help pages or AccountsController directly, a runtime exception is raised:
System.InvalidOperationException occurred
HResult=-2146233079
Message=No service registered for type 'ITableControllerConfigProvider'.Please ensure that the dependency resolver has been configured correctly.
Source=Microsoft.WindowsAzure.Mobile.Service
StackTrace:
at System.Web.Http.DependencyScopeExtensions.GetServiceOrThrow[TService](IDependencyScope services)
at Microsoft.WindowsAzure.Mobile.Service.Tables.TableControllerConfigAttribute.Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
at System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)
at System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)
at System.Web.Http.Controllers.HttpControllerDescriptor..ctor(HttpConfiguration configuration, String controllerName, Type controllerType)
at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.InitializeControllerInfoCache()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.GetControllerMapping()
at System.Web.Http.Description.ApiExplorer.InitializeApiDescriptions()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at System.Web.Http.Description.ApiExplorer.get_ApiDescriptions()
at MyMobileApp.Mvc.Areas.HelpPage.Controllers.HelpController.Index() in C:\tfs\MyMobileApp\dotNET\Web\MyMobileApp.Mvc\Areas\HelpPage\Controllers\HelpController.cs:line 31
InnerException:
Does anyone know what the problem with this could be? Do I need to explicitly register the mobile service assemblies and if so, what's the best way of doing that?
This is now resolved.
Just to wrap this up, the basic problem was that I'd changed the WebApiConfig.Register method so that it was non standard. I'd changed it from this
public static void Register()
to this
public static void Register(HttpConfiguration config)
and was attempting to use it like one would a standard Mvc webapi configuration from Global.asax.cs
Once I changed it back, I was able to register objects using autofac in the method like this:
builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
builder.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerRequest();
builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<ApplicationContext>())).AsImplementedInterfaces().InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();
builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>
{
DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("Application​")
});
without any problem
thanks

how register an interface that has no implentation with autofac?

How you I register an interface that has no implentation using Autofac?
I want Autofac to use DynamicProxy to generate interface your me!
builder.RegisterType(typeof(IUserDao))
.AsImplementedInterfaces()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(SqlMapperInterceptor));
public class SqlMapperInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
//todo: mapper sql file and return data
}
}
There is currently no mechanism to achieve this through the DynamicProxy2 integration provided by Autofac, but it can still be done by registering the generated proxy interface with Autofac directly:
builder.Register(c =>
{
var proxyGen = new ProxyGenerator();
return proxyGen.CreateInterfaceProxyWithoutTarget<IUserDao>(new SqlMapperInterceptor());
})
.As<IUserDao>();
There must be something to intercept, otherwise it isn't interception. The solution is to create a dummy IUserDao implementation a.k.a. Null Object Pattern. This dummy cwn be registered as implementation in Autofac.