cannot convert from 'method group' to 'Func<ApplicationRoleManager> in asp mvc identity - asp.net-mvc

this code for create a role in database .
IdentityConfig:
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(RoleStore<IdentityRole> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IOwinContext context)
{
var roleStore = new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>());
return new ApplicationRoleManager(roleStore);
}
}
but in Startup.Auth show me error :
How can I solve this error ?
Edit
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}

Signature for CreatePerOwingContext<T> looks like this:
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app, Func<IdentityFactoryOptions<T>, IOwinContext, T> createCallback) where T : class, IDisposable
or like this:
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app, Func<T> createCallback) where T : class, IDisposable
I.e. you ether need to provide a function that will create you an object, i.e.
app.CreatePerOwinContext<ApplicationRoleManager>(() => new ApplicationRoleManager(/*blah params*/));
This will be using second override. Or go back to defaults:
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
var applicationDbContext = context.Get<ApplicationDbContext>();
var roleStore = new RoleStore<IdentityRole>(applicationDbContext);
var manager = new ApplicationRoleManager(roleStore);
return manager;
}

Related

Autofac trouble

I'm new to using Autofac and Dependency injection and have been reading a lot on it. I'm getting an error message:"None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Evaluate.DivisionsController' can be invoked with the available services and parameters:
Cannot resolve parameter 'Evaluate.Services.DivisionService service' of constructor 'Void .ctor(Evaluate.Services.DivisionService)'."
I'm sure my issue is in the syntax I'm using for the configuration.
Here is my configuration in global.asax
//Autofac Configuration
var builder = new Autofac.ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
//builder.RegisterModule(new ServiceModule());
builder.RegisterModule(new EFModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
My EFModule:
builder.RegisterType(typeof(ApplicationDbContext)).As(typeof(IApplicationDbContext)).InstancePerRequest();
builder.RegisterType<UserProvider>().As<IUserProvider>().InstancePerRequest();
builder.RegisterType<DivisionService>().As<IDivisionService>().InstancePerRequest();
Controller:
private DivisionService _divisionService;
public DivisionsController(DivisionService service)
{
_divisionService = service;
}
Division Service:
public class DivisionService : BaseService<Division>, IDivisionService
{
//private IApplicationDbContext _context;
public DivisionService(IApplicationDbContext context)
:base(context)
{
}
ApplicationDBContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
private IUserProvider _user;
public ApplicationDbContext(IUserProvider user)
: base("DefaultConnection", throwIfV1Schema: false)
{
_user = user;
}
User Provider class:
public class UserProvider : IUserProvider
{
public string GetApplicationUserName()
{
return HttpContext.Current.User.ToString();
}
}
I have figured it out. The IDivisionService wasn't inheriting from the IBaseService

can't return roles in AspNetRoles

i need to return all role in identity tabel for create a dropdown list .
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(RoleStore<IdentityRole> store)
: base(store)
{
}
public static ApplicationRoleManager Create(IOwinContext context)
{
var Store = new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>());
// Configure validation logic for usernames
return new ApplicationRoleManager(Store);
}
}
how should i do this ?
Edit
/*******************************************************************************************************/
The process to get all roles via setting up ApplicationRoleManager is the following (as per Identity samples provided by Microsoft found here).
Add the code below to your IdentityConfig.cs
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
}
}
Then initialize the single instance per Owin context of your RoleManager in Startup.Auth.cs:
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
In your controller where you want to get all roles, do the following:
private ApplicationRoleManager _roleManager;
public ApplicationRoleManager RoleManager
{
get
{
return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
}
private set
{
_roleManager = value;
}
}
After that you can simply use RoleManager.Roles in any of your action methods to get all roles.
This answer contains all the steps you need to get this to work but refer to the link to the nuget package above if you're still unclear on the process.

MVC 6 (vNext) UserManager - DI - create user in specific database

I'm developing multitenant application. I use separate databases for each tenant. UserData are for each tenant in separate database TOO.
My problem is how can i create admin account for each tenant in "custom" database independently on DI. In MVC 5 was possible to instantiate UserManager base on UserStore(connection string). But UserManager in mvc6 depends on HttpContext... No documentation found...
Exist please some way how to do it??? I need in mvc 6 something like this in mvc 5:
UserStore<TenantUser> store = new UserStore<TenantUser>(new TenantDbContext("CONNECTION STRING")); //!!! NO POSSIBLE CREATE USER IN CUSTOM DATABASE
UserManager<TenantUser> t = new UserManager<TenantUser>(store);
t.CreateAsync(user, password);
Update:
public class TenantDbContext : IdentityDbContext<TenantUser, TenantRole, Guid>
{
private string _connectionString { get; set; }
private readonly IHttpContextAccessor _contextAccessor;
private readonly ApplicationDbContext _applicationDbContext;
//THIS SUB UNCOMENT ONLY IF CREATE MIGRATIONS (dnx ef...)
/*
public TenantDbContext(DbContextOptions<TenantDbContext> options) : base(options)
{
this._connectionString = "CONNECTION STRING";
}
*/
public TenantDbContext(DbContextOptions<TenantDbContext> options, IHttpContextAccessor contextAccessor, ApplicationDbContext applicationDbContext) : base(options) {
_contextAccessor = contextAccessor;
_applicationDbContext = applicationDbContext;
TenantResolver resolver = new TenantResolver(_contextAccessor, _applicationDbContext);
string con = resolver.GetConnectionString();
if (con != string.Empty)
{
this._connectionString = con; }
else
{
this._connectionString = "CONNECTION STRING"; //Development connection string
}
}
public TenantDbContext() //Posibility to create TenantDbContext migration and development database with no connectionString in constructor
{
//this._connectionString = "CONNECTION STRING";
}
public TenantDbContext(string ConnectionString)
{
this._connectionString = ConnectionString;
}
public static TenantDbContext Create(string ConnectionString)
{
return new TenantDbContext(ConnectionString);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_connectionString);
}
I hope that I correctly understand you. Let us we forget about the performance and the caching of multiple connections, which already opened to the databases. I suppose that you have multiple databases, which have the same schema. You need to access the databases using (sharing) the same database context.
I can suggest you two solutions.
The first solution consists from registering one context and reopening it if the one opened co change the connection string.
Let us you have TenantDbContext, which could be opened with different destination databases. For example with
#"Server=(localdb)\mssqllocaldb;Database=TenantDb1;Trusted_Connection=True;"
or
#"Server=(localdb)\mssqllocaldb;Database=TenantDb2;Trusted_Connection=True;"
First of all you remove OnConfiguring like
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=TenantDb;Trusted_Connection=True;");
}
which could exist in the definition of TenantDbContext and you use the following code in ConfigureServices of Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
var connection1 = #"Server=(localdb)\mssqllocaldb;Database=TenantDb1;Trusted_Connection=True;";
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<TenantDbContext>(options => options.UseSqlServer(connection1));
services.AddMvc();
...
}
In the way you inject TenantDbContext with one from the database (TenantDb1). Let us the TenantDbContext contains some entity set like Blog for example. Thus your can define some MVC controller in the following way
public class TenantsController : Controller
{
private TenantDbContext _context;
public TenantsController (TenantDbContext context)
{
_context = context;
}
public IActionResult Index() {
var con = _context.Database.GetDbConnection();
// now the con uses either TenantDb2 or TenantDb2
// con.ConnectionString can be used to get or set the
// connection string
string needConStr = #"Server=(localdb)\mssqllocaldb;Database=TenantDb2;Trusted_Connection=True;";
if (con.ConnectionString != needConStr) { // can be compared more carefully
_context.Database.CloseConnection();
con.ConnectionString = needConStr;
}
// get some data from the TenantDbContext
var blog = _context.Blog.ToList();
return View(blog);
}
}
The second solution don't need to inject any TenantDbContext using DependencyInjection. Instead of that you need just add one simple constructor to TenantDbContext:
public TenantDbContext(DbContextOptions optionsBuilder): base (optionsBuilder)
{
}
Such simple constructor will allows you to create the context at any time when you need it:
public class TenantsController : Controller
{
public IActionResult Index() {
var contextOptions = new DbContextOptionsBuilder();
contextOptions.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=TenantDb2;Trusted_Connection=True;");
var context = new BloggingContext(contextOptions.Options);
context.Database.OpenConnection();
// get some data from the TenantDbContext
var blog = context.Blog.ToList();
return View(blog);
}
}
I used all the connection strings directly in the code. You can easy modify the above code to get all connection strings from the config file appsettings.json.
Solved.
1. CreateCustomUserStore
public class TenantUserStore : UserStore<TenantUser, TenantRole, TenantDbContext, Guid>
{
public TenantUserStore(TenantDbContext context, IdentityErrorDescriber describer = null): base(context, describer)
{
}
}
And here is code how to instantiate UserManager with custom database:
IUserStore<TenantUser> CustomStore = new TenantUserStore(new TenantDbContext(coonection), null);
UserManager<TenantUser> manager = new UserManager<TenantUser>(CustomStore, _optionsAccessor, _passwordHasher, _userValidators,
_passwordValidators, _keyNormalizer, _errors, _services, _logger, _contextAccessor);
And DI used only for rest of UserManager Constructor:
public class TenantsController : Controller
{
private readonly IHttpContextAccessor _contextAccessor;
private readonly IOptions<IdentityOptions> _optionsAccessor;
private readonly IPasswordHasher<TenantUser> _passwordHasher;
private readonly IEnumerable<IUserValidator<TenantUser>> _userValidators;
private readonly IEnumerable<IPasswordValidator<TenantUser>> _passwordValidators;
private readonly ILookupNormalizer _keyNormalizer;
private readonly IdentityErrorDescriber _errors;
private readonly IServiceProvider _services;
private readonly ILogger<UserManager<TenantUser>> _logger;
public TenantsController(IHttpContextAccessor contextAccessor,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TenantUser> passwordHasher,
IEnumerable<IUserValidator<TenantUser>> userValidators,
IEnumerable<IPasswordValidator<TenantUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<UserManager<TenantUser>> logger
)
{
_optionsAccessor = optionsAccessor;
_passwordHasher = passwordHasher;
_userValidators = userValidators;
_passwordValidators = passwordValidators;
_keyNormalizer = keyNormalizer;
_errors = errors;
_services = services;
_logger = logger;
_contextAccessor = contextAccessor;
}

How do I inject Identity classes with Ninject?

I'm trying to use UserManager in a class, but I'm getting this error:
Error activating IUserStore{ApplicationUser}
No matching bindings are available, and the type is not self-bindable.
I'm using the default Startup.cs, which sets a single instance per request:
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
I'm able to get the ApplicationDbContext instance, which I believe is getting injected by Owin (Is that true?):
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private ApplicationDbContext context;
public GenericRepository(ApplicationDbContext context)
{
this.context = context;
}
}
But I can't do the same with UserManager (It throws the error shown before):
public class AnunciosService : IAnunciosService
{
private IGenericRepository<Anuncio> _repo;
private ApplicationUserManager _userManager;
public AnunciosService(IRepositorioGenerico<Anuncio> repo, ApplicationUserManager userManager)
{
_repo = repo;
_userManager = userManager;
}
}
The controller uses the UserManager like this:
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
I'm using ninject to inject my other classes, but how do I inject the UserManager with it's dependencies and avoid using it like that in my controllers?
I injected It like this
kernel.Bind<IUserStore<ApplicationUser>>().To<UserStore<ApplicationUser>>();
kernel.Bind<UserManager<ApplicationUser>>().ToSelf();
And now It's working as it should.
OP's answer didn't work for me, as I was using a custom ApplicationUser class that has long as a key instead of string .
Hence, I created a generic static method the would get the OwinContext from the current HttpContext and return the desired concrete implementation.
private static T GetOwinInjection<T>(IContext context) where T : class
{
var contextBase = new HttpContextWrapper(HttpContext.Current);
return contextBase.GetOwinContext().Get<T>();
}
I then used GetOwinInjection method for injection like this:
kernel.Bind<ApplicationUserManager>().ToMethod(GetOwinInjection<ApplicationUserManager>);
kernel.Bind<ApplicationSignInManager>().ToMethod(GetOwinInjection<ApplicationSignInManager>);
If you are also using IAuthenticationManger, you should inject it like this:
kernel.Bind<IAuthenticationManager>().ToMethod(context =>
{
var contextBase = new HttpContextWrapper(HttpContext.Current);
return contextBase.GetOwinContext().Authentication;
});

Web API, odata v4 and Castle Windsor

I have WebApi project with ODataController and I'm trying to inject some dependency into MyController. I was following this blogpost by Mark Seemann.
Consider code below.
Problem is, that when is MyController creating, I got exception inside WindsorCompositionRoot Create method on this line,
var controller = (IHttpController)this.container.Resolve(controllerType);
An exception of type 'Castle.MicroKernel.ComponentNotFoundException'
occurred in Castle.Windsor.dll but was not handled in user code
Additional information: No component for supporting the service
System.Web.OData.MetadataController was found
Any idea how to fix this?
Thank you.
My controller:
public class MyController : ODataController
{
private readonly DataLayer _db;
public PrepravyController(DataLayer db)
{
_db = db;
}
}
CompositonRoot:
public class WindsorCompositionRoot : IHttpControllerActivator
{
private readonly IWindsorContainer container;
public WindsorCompositionRoot(IWindsorContainer container)
{
this.container = container;
}
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var controller =
(IHttpController)this.container.Resolve(controllerType);
request.RegisterForDispose(
new Release(
() => this.container.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action release;
public Release(Action release)
{
this.release = release;
}
public void Dispose()
{
this.release();
}
}
}
Global asax:
var container = new WindsorContainer();
container.Install(new RepositoriesInstaller());
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorCompositionRoot(container));
GlobalConfiguration.Configure(WebApiConfig.Register);
Make sure you're registering all your controllers with the container:
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestylePerWebRequest())
.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest());
}
}
Windsor uses installers to encapsulate and partition registration logic. It also includes a helper called FromAssembly, so you don't need to manually instantiate all your installers:
_container = new WindsorContainer();
_container.Install(FromAssembly.This());

Resources