问题
I have a custom MembershipProvider class that inherits from MembershipProvider that takes two parameters:
public class CustomMembershipProvider : MembershipProvider
{
private readonly ISecurityRepository _securityRepository;
private readonly IUserRepository _userRepository;
public CustomMembershipProvider(ISecurityRepository securityRepository, IUserRepository userRepository)
{
...
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
...
}
... etc
}
The config file for this looks similar to this:
<membership defaultProvider="CustomMembershipProvider">
<providers>
<clear />
<add name="CustomMembershipProvider" type="Library.Membership.CustomMembershipProvider" />
</providers>
</membership>
This works fine mostly throughout my web application for logging in and logging out. I am using Unity for DI and have the necessary classes setup in my Boostrapper.cs class.
However I recently ran into an issue when I wanted to create a custom User class and called the Membership.GetUser method. I get the following exception when I do:
{"No parameterless constructor defined for this object. (C:\\*app path*\\web.config line 43)"}
Line 43 in my config file points to the custom membership provider that I posted above. I think that elsewhere the app is using Unity to resolve those parameters but when using the Membership class it doesn't.
Is there any way I can tell the application how to resolve those dependencies or if not is there a way of adding those dependencies to my membership provider without using the concrete implementation?
EDIT 1:
Here is the custom User class:
public class User : MembershipUser
{
public int UserId { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public DateTime LastLoggedOnDate { get; set; }
...
}
EDIT 2:
In my custom membership provider class this is what the GetUser method looks like:
public override MembershipUser GetUser(string username, bool userIsOnline)
{
return _userRepository.GetUser(username);
}
回答1:
The problem is that you can't inject into the Membership provider via constructor. Refer to this question
I implemented a Custom Membership Provider using Ninject and I used the ServiceLocator to get the instance of the service.
public class AccountMembershipProvider : MembershipProvider
{
private readonly IUsers _users;
public AccountMembershipProvider()
{
_users = ServiceLocator.Current.GetInstance<IUsers>();
}
public override bool ValidateUser(string username, string password)
{
return _users.IsValidLogin(username, password);
}
...
}
In your case, you need to get the IUserRepository and ISecurityRepository.
When you wire your Interfaces/services
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUsers>().To<UsersService>();
kernel.Bind<IRoles>().To<RolesService>();
kernel.Bind<MembershipProvider>().To<AccountMembershipProvider>().InRequestScope();
kernel.Bind<RoleProvider>().To<AccountRoleProvider>().InRequestScope();
}
You can check a complete example of it working (using Ninject but you can adapt it to Unity) here: https://github.com/lopezbertoni/SampleApp
Hope this helps,
回答2:
I also use Unity and implemented a custom membership provider, but used a slightly different approach. Check the code sample:
/// <summary>
/// Defines the custom membership provider class.
/// </summary>
public class SsoMembershipProvider : MembershipProvider
{
private IApplicationsRepository _appsRepo;
private IUsersRepository _usersRepo;
private IMembershipsRepository _membershipsRepo;
/// <summary>
/// Initializes a new instance of the <see cref="SsoMembershipProvider"/> class
/// using injectionConstructor attribute in order to get the repositories needed.
/// </summary>
/// <param name="appsRepo">The apps repo.</param>
/// <param name="usersRepo">The users repo.</param>
/// <param name="membershipsRepo">The memberships repo.</param>
[InjectionConstructor]
public SsoMembershipProvider(IApplicationsRepository appsRepo, IUsersRepository usersRepo, IMembershipsRepository membershipsRepo)
{
_appsRepo = appsRepo;
_usersRepo = usersRepo;
_membershipsRepo = membershipsRepo;
}
/// <summary>
/// Initializes a new instance of the <see cref="SsoMembershipProvider"/> class.
/// which calls the internal contructor.
/// </summary>
/// <remarks>This is happening due to the fact that membership provider needs a
/// parametless constructor to be initialized</remarks>
public SsoMembershipProvider()
: this(DependencyResolver.Current.GetService<IApplicationsRepository>(),
DependencyResolver.Current.GetService<IUsersRepository>(),
DependencyResolver.Current.GetService<IMembershipsRepository>())
{ }
}
回答3:
This worked for me
public ICustomerRepository CustomerRepository {
get { return DependencyResolver.Current.GetService<ICustomerRepository>(); }
}
and then use
public override bool ValidateUser(string username, string password)
{
var abc = CustomerRepository.ValidateCustomer(username, password);
}
来源:https://stackoverflow.com/questions/20903058/custom-membershipprovider-no-parameterless-constructor-defined-for-this-object