Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom MembershipProvider: No parameterless constructor defined for this object

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);
}
like image 842
Serberuss Avatar asked Jan 03 '14 11:01

Serberuss


People also ask

Is there a parameterless constructor defined for this object?

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.

Why model binding looks for paremeterless Constructors?

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.

Why does MVC need a parameterless constructor for employeecontroller?

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

What happens when you define a class without a 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.


2 Answers

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,

like image 73
lopezbertoni Avatar answered Sep 24 '22 21:09

lopezbertoni


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>())
    { }


}
like image 43
mitsbits Avatar answered Sep 24 '22 21:09

mitsbits