Method FindByLoginAsync doesn't work correctly with AspNetCore.Identity - asp.net-core

I have used the AspNetCore.Identity in my Asp.Net Core application and I want to call the method called FindByLoginAsync but result is always NULL.
Versions:
Microsoft.AspNetCore.Identity.EntityFrameworkCore (1.1.1)
Microsoft.AspNetCore.Identity (1.1.1)
Code:
var loginProvider = "Github"
var providerKey = "1234567";
var user = await _userManager.FindByLoginAsync(loginProvider, providerKey);
This record exists in the database, but this method returns always NULL.
I've tried trace the SQL query and I've got this:
exec sp_executesql N'SELECT TOP(1) [e].[ProviderKey], [e].[LoginProvider], [e].[ProviderDisplayName], [e].[UserId]
FROM [UserLogins] AS [e]
WHERE ([e].[ProviderKey] = #__get_Item_0) AND ([e].[LoginProvider] = #__get_Item_1)',N'#__get_Item_0 nvarchar(450),#__get_Item_1 nvarchar(450)',#__get_Item_0=N'Github',#__get_Item_1=N'1234567'
My SQL query is like [e].[LoginProvider] the value providerKey and [e].[ProviderKey] the value loginProvider.
Application DbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>(i =>
{
i.ToTable("Users");
i.HasKey(x => x.Id);
});
builder.Entity<ApplicationRole>(i =>
{
i.ToTable("Roles");
i.HasKey(x => x.Id);
});
builder.Entity<IdentityUserRole<int>>(i =>
{
i.ToTable("UserRoles");
i.HasKey(x => new { x.RoleId, x.UserId });
});
builder.Entity<IdentityUserLogin<int>>(i =>
{
i.ToTable("UserLogins");
i.HasKey(x => new { x.ProviderKey, x.LoginProvider });
});
builder.Entity<IdentityRoleClaim<int>>(i =>
{
i.ToTable("RoleClaims");
i.HasKey(x => x.Id);
});
builder.Entity<IdentityUserClaim<int>>(i =>
{
i.ToTable("UserClaims");
i.HasKey(x => x.Id);
});
builder.Entity<IdentityUserToken<int>>(i =>
{
i.ToTable("UserTokens");
i.HasKey(x => x.UserId);
});
}
}
Implementation of IdentityUser, IdentityRole
public class ApplicationUser : IdentityUser<int>
{
}
public class ApplicationRole : IdentityRole<int>
{
}
How can I fix this? How is this behaviour possible?

You have incorrect order of primary keys in registration of entity IdentityUserLogin. Change it to this
builder.Entity<IdentityUserLogin<int>>(i =>
{
i.ToTable("UserLogins");
i.HasKey(x => new { x.LoginProvider, x.ProviderKey });
});
That's the fix, now the rationale behind.
In version 1.1.1 the method UserStore.FindByLoginAsync used method DbSet.FindAsync, which accepts ordered array of values for primary keys. The order must follow the order used in entity registration.
public async virtual Task<TUser> FindByLoginAsync(string loginProvider, string providerKey,
CancellationToken cancellationToken = default(CancellationToken))
{
...
var userLogin = await UserLogins.FindAsync(new object[] { loginProvider, providerKey }, cancellationToken);
...
}
In the default implementation the primary keys are registered in correct order
builder.Entity<TUserLogin>(b =>
{
b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
b.ToTable("AspNetUserLogins");
});

Related

Blazor WASM Authentication along with Blazor Server Authentication

When using ApiAuthorizationDbContext WASM Fetch page authenticates and passes the token, but Razor pages will not authenticate. When switching to IdentityDbContext, the opposite happens, I am able to authenticate the razor page but WASM fetch page will not authenticate. I have a very simple sample at https://github.com/williameduardo79/BlazorServerClientSample
This works well with Blazor WASM
public class ApplicationDbContext : ApiAuthorizationDbContext<ApplicationUser>
{
public ApplicationDbContext(
DbContextOptions options,
IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options, operationalStoreOptions)
{
}
}
This works well with Blazor Pages
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
How can I make it work?
Any references are appreciated :)
Can you share your server's Startup.cs file? Specifically where you are registering/configuring the services for Identity/DbContexts. IdentityDbContext is basically the same as ApiAuthorizationDbContext but it adds the required DbSets for Persisted Grants and Device Flow Codes for enabling API-based authentication.
I have a working IdentityDbContext for both MVC Razor pages and Blazor WASM so I know it is possible! :) The difference being I implemented the types explicitly:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string,
IdentityUserClaim<string>, ApplicationUserRole, IdentityUserLogin<string>, IdentityRoleClaim<string>,
IdentityUserToken<string>>, IPersistedGrantDbContext
{
private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;
public ApplicationDbContext(DbContextOptions options, IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options)
{
_operationalStoreOptions = operationalStoreOptions;
}
public DbSet<ApplicationUser> ApplicationUser { get; set; }
public DbSet<PersistedGrant> PersistedGrants { get; set; }
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
Task<int> IPersistedGrantDbContext.SaveChangesAsync() => base.SaveChangesAsync();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
// Override default AspNet Identity table names
modelBuilder.Entity<ApplicationUser>().Property(x => x.Created).HasDefaultValueSql("getdate()");
modelBuilder.Entity<ApplicationUser>(entity => { entity.ToTable(name: "Users"); });
modelBuilder.Entity<ApplicationRole>(entity => { entity.ToTable(name: "Roles"); });
modelBuilder.Entity<DeviceFlowCodes>(entity => { entity.ToTable("UserDeviceCodes"); });
modelBuilder.Entity<PersistedGrant>(entity => { entity.ToTable("UserPersistedGrants"); });
modelBuilder.Entity<ApplicationUserRole>(entity =>
{
entity.ToTable("UserRoles");
entity.HasKey(x => new { x.UserId, x.RoleId });
entity.HasOne(ur => ur.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
entity.HasOne(ur => ur.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
modelBuilder.Entity<IdentityUserClaim<string>>(entity => { entity.ToTable("UserClaims"); });
modelBuilder.Entity<IdentityUserLogin<string>>(entity => { entity.ToTable("UserLogins"); });
modelBuilder.Entity<IdentityUserToken<string>>(entity => { entity.ToTable("UserTokens"); });
modelBuilder.Entity<IdentityRoleClaim<string>>(entity => { entity.ToTable("RoleClaims"); });
}
}
In my Startup.cs file:
// ASP.NET Identity
services.AddDefaultIdentity<ApplicationUser>(options =>
{
options.User.RequireUniqueEmail = true;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
})
.AddRoles<ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
// Identity Server
var identityServerBuilder = services.AddIdentityServer(options =>
{
options.Authentication.CookieSlidingExpiration = true;
options.Authentication.CookieLifetime = TimeSpan.FromDays(7);
}).AddAspNetIdentity<ApplicationUser>()
.AddOperationalStore<ApplicationDbContext>()
.AddIdentityResources()
.AddApiResources()
.AddClients();

Swagger versioning is not working. It displays all endpoints, despite the selected API version

all!
I am using Swagger in ASP.NET Core 3.1 application.
I need to create an endpoint for the new version of API and with the same route as a previous version.
My controller is:
namespace Application.Controllers
{
[ApiVersion("1")]
[ApiVersion("2")]
[ApiController]
[Route("api/v{version:apiVersion}")]
public class CustomController: ControllerBase
{
[HttpGet]
[Route("result")]
public IActionResult GetResult()
{
return Ok("v1")
}
[HttpGet]
[MapToApiVersion("2")]
[Route("result")]
public IActionResult GetResult(int number)
{
return Ok("v2")
}
}
}
My configuration:
services.AddApiVersioning(
options =>
{
options.ReportApiVersions = true;
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc($"v1", new OpenApiInfo { Title = "api1", Version = $"v1" });
c.SwaggerDoc($"v2", new OpenApiInfo { Title = "api2", Version = $"v2" });
c.OperationFilter<RemoveVersionParameterFilter>();
c.DocumentFilter<ReplaceVersionWithExactValueInPathFilter>();
c.EnableAnnotations();
});
app.UseSwagger().UseSwaggerUI(c =>
{
c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"api1 v1");
c.SwaggerEndpoint($"/swagger/v2/swagger.json", $"api2 v2");
});
After loading I get an error: Fetch error undefined /swagger/v1/swagger.json
But If I change the second route to the "resutlTwo", I can observe both endpoints in swagger, ignoring current version (api1 v1 or api2 v2)
How can I see only 1 endpoint per API version?
Thanks Roar S. for help!
I just added
services.AddApiVersioning(apiVersioningOptions =>
{
apiVersioningOptions.ReportApiVersions = true;
apiVersioningOptions.ApiVersionReader = new UrlSegmentApiVersionReader();
});
and
c.DocInclusionPredicate((version, desc) =>
{
var endpointMetadata = desc.ActionDescriptor.EndpointMetadata;
if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
{
return false;
}
var specificVersion = endpointMetadata
.Where(data => data is MapToApiVersionAttribute)
.SelectMany(data => (data as MapToApiVersionAttribute).Versions)
.Select(apiVersion => apiVersion.ToString())
.SingleOrDefault();
if (!string.IsNullOrEmpty(specificVersion))
{
return $"v{specificVersion}" == version;
}
var versions = endpointMetadata
.Where(data => data is ApiVersionAttribute)
.SelectMany(data => (data as ApiVersionAttribute).Versions)
.Select(apiVersion => apiVersion.ToString());
return versions.Any(v => $"v{v}" == version);
});
And it split endpoints to different files.
I just tested your case with this setup.You are missing UrlSegmentApiVersionReader.
public class SwaggerOptions
{
public string Title { get; set; }
public string JsonRoute { get; set; }
public string Description { get; set; }
public List<Version> Versions { get; set; }
public class Version
{
public string Name { get; set; }
public string UiEndpoint { get; set; }
}
}
In Startup#ConfigureServices
// Configure versions
services.AddApiVersioning(apiVersioningOptions =>
{
apiVersioningOptions.ReportApiVersions = true;
apiVersioningOptions.ApiVersionReader = new UrlSegmentApiVersionReader();
});
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(swaggerGenOptions =>
{
var swaggerOptions = new SwaggerOptions();
Configuration.GetSection("Swagger").Bind(swaggerOptions);
foreach (var currentVersion in swaggerOptions.Versions)
{
swaggerGenOptions.SwaggerDoc(currentVersion.Name, new OpenApiInfo
{
Title = swaggerOptions.Title,
Version = currentVersion.Name,
Description = swaggerOptions.Description
});
}
swaggerGenOptions.DocInclusionPredicate((version, desc) =>
{
if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
{
return false;
}
var versions = methodInfo.DeclaringType.GetConstructors()
.SelectMany(constructorInfo => constructorInfo.DeclaringType.CustomAttributes
.Where(attributeData => attributeData.AttributeType == typeof(ApiVersionAttribute))
.SelectMany(attributeData => attributeData.ConstructorArguments
.Select(attributeTypedArgument => attributeTypedArgument.Value)));
return versions.Any(v => $"{v}" == version);
});
swaggerGenOptions.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"));
... some filter settings here
});
In Startup#Configure
var swaggerOptions = new SwaggerOptions();
Configuration.GetSection("Swagger").Bind(swaggerOptions);
app.UseSwagger(option => option.RouteTemplate = swaggerOptions.JsonRoute);
app.UseSwaggerUI(option =>
{
foreach (var currentVersion in swaggerOptions.Versions)
{
option.SwaggerEndpoint(currentVersion.UiEndpoint, $"{swaggerOptions.Title} {currentVersion.Name}");
}
});
appsettings.json
{
"Swagger": {
"Title": "App title",
"JsonRoute": "swagger/{documentName}/swagger.json",
"Description": "Some text",
"Versions": [
{
"Name": "2.0",
"UiEndpoint": "/swagger/2.0/swagger.json"
},
{
"Name": "1.0",
"UiEndpoint": "/swagger/1.0/swagger.json"
}
]
}
}
This code is very similar to a related issue I'm working on here on SO.

How to create DbContext

below default code in controller working fine
public ProductController(appDbContext parmContext)
{
_context = parmContext;
}
now I want to add DAL and in that, getting error creating object of type appDbContext, what to pass/set for parmContext?
below is the connection in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDbContext<appDbContext>(config =>
{
config.UseMySql(Configuration.GetConnectionString("PreSales"));
});
}
Below is the code I want to use
public IEnumerable<ProductStatusMaster> GetProductStatusFRdal()
// here I ant to create object of DBcontext (i.e. _context)
{
try
{
var msm = _context.ProductStatusMaster
.Where(s => s.ActiveYn == 1 )
.OrderBy(s => s.Status)
.ToList();
return msm;
}
catch
{
throw;
}
}
Let me get an answer.
There are 2 ways to realize code you want.
1) Through Controller DI.
2) Through Service Locator pattern (antipattern).
By the code:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDbContext<appDbContext>(config =>
{
config.UseMySql(Configuration.GetConnectionString("PreSales"));
});
}
you set up dependency for DbContext and configure connection parameters. So, for the first method you should pass the dependency through controller. Possible code will be like this:
public class MyTestAppController
{
private appDbContext _context;
public MyTestApController(appDbContext externalAppDbContext)
{
_context = externalAppDbContext;
}
public IEnumerable<ProductStatusMaster> GetProductStatusFRdal()
{
try
{
var msm = _context.ProductStatusMaster
.Where(s => s.ActiveYn == 1 )
.OrderBy(s => s.Status)
.ToList();
return msm;
}
catch
{
throw;
}
}
}
2) Using Service Locator pattern
In this case you should use IServiceProvider dependency. Code example like this:
public class MyTestAppController
{
private IServiceProvider _provider;
public MyTestAppController(IServiceProvider provider) => _provider = provider;
public IEnumerable<ProductStatusMaster> GetProductStatusFRdal()
{
var _context = _provider.GetService<appDbContext>();
try
{
var msm = _context.ProductStatusMaster .Where(s => s.ActiveYn == 1 )
.OrderBy(s => s.Status) .ToList(); return msm;
}
catch { throw; }
}
}

CQRS ValidatorHandler not recognizing FluentValidation validators?

I'm using Web Api 2, Autofac, and MediatR (CQRS). I have a mediator pipeline in place that has pre/post request handlers. That all works fine. I'm trying to hook up Validation now and decorate the pipeline with it.
Here is my Autofac DI code:
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
FluentValidationModelValidatorProvider.Configure(config);
ConfigureDependencyInjection(app, config);
WebApiConfig.Register(config);
app.UseWebApi(config);
}
private static void ConfigureDependencyInjection(IAppBuilder app, HttpConfiguration config)
{
var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsImplementedInterfaces();
builder.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => c.Resolve(t);
});
builder.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
});
//register all pre handlers
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As(type => type.GetInterfaces()
.Where(interfacetype => interfacetype.IsClosedTypeOf(typeof(IAsyncPreRequestHandler<>))))
.InstancePerLifetimeScope();
//register all post handlers
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As(type => type.GetInterfaces()
.Where(interfacetype => interfacetype.IsClosedTypeOf(typeof(IAsyncPostRequestHandler<,>))))
.InstancePerLifetimeScope();
//register all async handlers
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As(type => type.GetInterfaces()
.Where(interfaceType => interfaceType.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>)))
.Select(interfaceType => new KeyedService("asyncRequestHandler", interfaceType)))
.InstancePerLifetimeScope();
//register pipeline decorator
builder.RegisterGenericDecorator(
typeof(AsyncMediatorPipeline<,>),
typeof(IAsyncRequestHandler<,>),
"asyncRequestHandler")
.Keyed("asyncMediatorPipeline", typeof(IAsyncRequestHandler<,>))
.InstancePerLifetimeScope();
//register validator decorator
builder.RegisterGenericDecorator(
typeof(ValidatorHandler<,>),
typeof(IAsyncRequestHandler<,>),
"asyncMediatorPipeline")
.InstancePerLifetimeScope();
// Register Web API controller in executing assembly.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
//register RedStripeDbContext
builder.RegisterType<RedStripeDbContext>().As<IRedStripeDbContext>().InstancePerRequest();
builder.RegisterType<AutofacServiceLocator>().AsImplementedInterfaces();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// This should be the first middleware added to the IAppBuilder.
app.UseAutofacMiddleware(container);
// Make sure the Autofac lifetime scope is passed to Web API.
app.UseAutofacWebApi(config);
}
Here is the ValidatorHandler:
public class ValidatorHandler<TRequest, TResponse> : IAsyncRequestHandler<TRequest, TResponse> where TRequest : IAsyncRequest<TResponse>
{
private readonly IAsyncRequestHandler<TRequest, TResponse> _inner;
private readonly IValidator<TRequest>[] _validators;
public ValidatorHandler(
IAsyncRequestHandler<TRequest, TResponse> inner,
IValidator<TRequest>[] validators)
{
_inner = inner;
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request)
{
var context = new ValidationContext(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
throw new ValidationException(failures);
return await _inner.Handle(request);
}
}
Here is a sample query:
[Validator(typeof(GetAccountRequestValidationHandler))]
public class GetAccountRequest : IAsyncRequest<GetAccountResponse>
{
public int Id { get; set; }
}
Here is the fluent validation handler:
public class GetAccountRequestValidationHandler : AbstractValidator<GetAccountRequest>
{
public GetAccountRequestValidationHandler()
{
RuleFor(m => m.Id).GreaterThan(0).WithMessage("Please specify an id.");
}
public Task Handle(GetAccountRequest request)
{
Debug.WriteLine("GetAccountPreProcessor Handler");
return Task.FromResult(true);
}
}
Here is the request handler:
public class GetAccountRequestHandler : IAsyncRequestHandler<GetAccountRequest, GetAccountResponse>
{
private readonly IRedStripeDbContext _dbContext;
public GetAccountRequestHandler(IRedStripeDbContext redStripeDbContext)
{
_dbContext = redStripeDbContext;
}
public async Task<GetAccountResponse> Handle(GetAccountRequest message)
{
return await _dbContext.Accounts.Where(a => a.AccountId == message.Id)
.ProjectToSingleOrDefaultAsync<GetAccountResponse>();
}
}
Finally here is the Web Api 2 HttpGet method:
[Route("{id:int}")]
[HttpGet]
public async Task<IHttpActionResult> GetById([FromUri] GetAccountRequest request)
{
var model = await _mediator.SendAsync<GetAccountResponse>(request);
return Ok(model);
}
I put breakpoints all over the place and when I hit this endpoint, the first thing I get into is the GetAccountRequestValidationHandler. Then I get into the ValidatorHandler's constructor. The problem is, the IValidator[] validators parameter to the constructor is always null.
I must be missing something with fluent validation and its registration via Autofac? Any help is much appreciated.
The validator types must be registered in the IoC. Adding the below to your ConfigureDependencyInjection method should do it.
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.EndsWith("ValidationHandler"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();

Error using Autofac.Extras.NHibernate

I'm trying to inject dependencies im my models that NHibernate creates.
What I'm trying to do is the same here: http://fabiomaulo.blogspot.com.br/2008/11/entities-behavior-injection.html
But my container is Autofac.
So, I've found https://www.nuget.org/packages/Autofac.Extras.NHibernate/
I saw the post http://chadly.net/2009/05/dependency-injection-with-nhibernate-and-autofac/ that I've think is the origin of the Autofac.Extras.NHibernate.
My problem is that the code in Autofac.Extras.NHibernate and described in Chad post are different.
Looking at the source code I (think) figured out how to set the BytecodeProvider using:
Cfg.Environment.BytecodeProvider = new AutofacBytecodeProvider(Container, new DefaultProxyFactoryFactory(), new DefaultCollectionTypeFactory());
But now, I'm getting an exception when I tried to retrieve data from database:
[PropertyAccessException: could not set a property value by reflection setter of NHibernate.Autofac2.App_Start.Model.User.Id]
If I comment the line where I set BytecodeProvider the code works.
I created a POC to simulate:
My model:
public class User
{
private readonly ISomeService _someService;
public User(ISomeService someService)
{
this._someService = someService;
}
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual string GetTranslate
{
get { return this._someService != null ? this._someService.T(this.Name) : " No Translate" + this.Name; }
}
}
My mapping:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.Id);
Map(x => x.Name)
.Length(16)
.Not.Nullable();
}
}
Creation of the Autofac container and SessionFactory using Fluent Nhibernate:
// Create your builder.
var builder = new ContainerBuilder();
builder.RegisterType<SomeService>().As<ISomeService>();
builder.RegisterType<User>().As<IUser>();
Container = builder.Build();
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString("Data Source=(local);Initial Catalog=NHibernate.Autofac;User ID=test;Password=102030;Pooling=True"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<MvcApplication>())
.ExposeConfiguration(config => config.Properties.Add("use_proxy_validator", "false"))
.ExposeConfiguration(config =>
{
//config.Properties.Add("proxyfactory.factory_class", "");
Cfg.Environment.BytecodeProvider = new AutofacBytecodeProvider(Container, new DefaultProxyFactoryFactory(), new DefaultCollectionTypeFactory());
new SchemaExport(config).Drop(false, false);
new SchemaExport(config).Create(false, true);
})
.BuildSessionFactory();
Well, I've found a solution that works for me.
Now, I'm using NHibernate.DependencyInjection.
The IEntityInjector implemenation:
public class EntityInjector : IEntityInjector
{
private readonly IContainer _container;
public EntityInjector(IContainer container)
{
_container = container;
}
public object[] GetConstructorParameters(System.Type type)
{
var constructor = type.GetConstructors().FirstOrDefault();
if (constructor != null)
return constructor.GetParameters().Select(a => a.ParameterType).Select(b => this._container.Resolve(b)).ToArray();
return null;
}
}
And in Global.asax:
Initializer.RegisterBytecodeProvider(new EntityInjector(Container));
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString("Data Source=(local);Initial Catalog=NHibernate.Autofac;User ID=XXX;Password=XXXX;Pooling=True"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<MvcApplication>())
.ExposeConfiguration(config => config.Properties.Add("use_proxy_validator", "false"))
.ExposeConfiguration(config =>
{
new SchemaExport(config).Drop(false, false);
new SchemaExport(config).Create(false, true);
})
.BuildSessionFactory();