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);
}
No parameterless constructor defined for this object. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
if you define a constructor in your class explicitly, then compiler will not add extra constructor. So if you add a constructor with parameter then Model binding will have no idea what values provide in this constructor parameter. That's why Model Binding looks for paremeterless constructor.
When creating controllers MVC assumes you have what is known as a parameterless constructor which means it can create it like this; MVC can create this fine as it doesn't need to know anything. For that to work your EmployeeController needs a parameterless constructor
When you define a simple class without constructor, then compiler will automatcally add a parameterless construstor during compilation. So this class if you define a constructor in your class explicitly, then compiler will not add extra constructor.
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,
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>())
{ }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With