【问题标题】:Custom MembershipProvider: No parameterless constructor defined for this object自定义 MembershipProvider:没有为此对象定义无参数构造函数
【发布时间】:2014-01-03 11:52:55
【问题描述】:

我有一个继承自 MembershipProvider 的自定义 MembershipProvider 类,它接受两个参数:

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
}

此配置文件看起来类似于:

<membership defaultProvider="CustomMembershipProvider">
  <providers>
    <clear />
    <add name="CustomMembershipProvider" type="Library.Membership.CustomMembershipProvider" />
  </providers>
</membership>

这在我用于登录和注销的 Web 应用程序中大部分都可以正常工作。我正在为 DI 使用 Unity,并在我的 Boostrapper.cs 类中设置了必要的类。

但是,当我想创建自定义 User 类并调用 Membership.GetUser 方法时,我最近遇到了一个问题。当我这样做时,我得到以下异常:

{"No parameterless constructor defined for this object. (C:\\*app path*\\web.config line 43)"}

我的配置文件中的第 43 行指向我在上面发布的自定义成员资格提供程序。我认为该应用程序在其他地方使用 Unity 来解析这些参数,但在使用 Membership 类时却没有。

有什么方法可以告诉应用程序如何解决这些依赖关系,或者如果没有,有没有办法在不使用具体实现的情况下将这些依赖关系添加到我的成员资格提供程序?

编辑 1:

这是自定义用户类:

public class User : MembershipUser
{
    public int UserId { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
    public DateTime LastLoggedOnDate { get; set; }
    ...         
}

编辑 2:

在我的自定义会员提供程序类中,GetUser 方法如下所示:

public override MembershipUser GetUser(string username, bool userIsOnline)
{
    return _userRepository.GetUser(username);
}

【问题讨论】:

  • 您还没有发布您的自定义用户类代码?这是错误的地方吗?
  • 不,错误是它无法解析自定义成员资格提供程序类。 User 类是一个非常简单的用户模板,带有属性(姓名、电子邮件、用户 ID 等)
  • GetUser 方法中有什么代码?这是错误被正确抛出的地方吗?你在你的问题中声明called the Membership.GetUser method. I get the following exception when I do:
  • 由于无法解析类,它实际上从未访问过该代码。但我将在中使用该代码更新帖子
  • 这很痛苦.. 我这周做到了。我最终将 DI 容器传递到自定义 MembershipProvider 中。省了很多麻烦..但它很脏。

标签: c# asp.net-mvc dependency-injection asp.net-membership unity-container


【解决方案1】:

问题是您不能通过构造函数注入成员资格提供程序。参考this question

我使用 Ninject 实现了一个自定义成员资格提供程序,并使用 ServiceLocator 来获取服务的实例。

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);
    }
...
}

在您的情况下,您需要获取 IUserRepository 和 ISecurityRepository。

当你连接你的接口/服务时

    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();

    }

您可以在此处查看其工作的完整示例(使用 Ninject,但您可以将其调整为 Unity):https://github.com/lopezbertoni/SampleApp

希望这会有所帮助,

【讨论】:

  • 同样,这会使您的 IOC 依赖于您的 MembershipProvider,这并不总是理想的,例如,如果您正在构建一个公共库。
  • 谢谢,这很有帮助
【解决方案2】:

我还使用 Unity 并实现了自定义成员资格提供程序,但使用了稍微不同的方法。查看代码示例:

/// <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】:

    这对我有用

    public ICustomerRepository CustomerRepository { 
     get { return DependencyResolver.Current.GetService<ICustomerRepository>(); } 
    }
    

    然后使用

    public override bool ValidateUser(string username, string password)
    {
        var abc = CustomerRepository.ValidateCustomer(username, password);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-29
      • 2016-04-25
      • 2018-02-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多