【问题标题】:Determine which construtor to be called(change default constructor) when an action is called in MVC Web API确定在 MVC Web API 中调用操作时要调用的构造函数(更改默认构造函数)
【发布时间】:2016-12-08 06:36:07
【问题描述】:

我正在使用 mvc web api。我有一个通用的 IRepository 和 IUnitOfWork 库,它在 asp.net mvc 中完美运行,但是当我打算在我的 mvc web api 项目中使用它时,我的存储库对象变为空,因此导致异常。我的存储库和 UnitOfWork 对象正在一个构造函数中被实例化和初始化,该构造函数将一个 IunitOfWork 对象作为参数

这里是代码(构造函数代码)

private IRepository<AspNetUserAccount> AccountRepository;
    private IRepository<Doctor> DoctorRepository;
    private readonly IUnitOfWork UnitOfWork;
    public AccountController(IUnitOfWork unitOfWork)
    {
        UnitOfWork = unitOfWork;
        AccountRepository = unitOfWork.Repository<AspNetUserAccount>();
        DoctorRepository = unitOfWork.Repository<Doctor>();
    }
    public AccountController()
    {

    }

这是我的 Repository 和 UnitOfWork 对象在 Account 控制器的 Register 操作中的用法。

 [AllowAnonymous]
 [Route("Register")]
 public ResultViewModel Register([FromBody]UserBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return new ResultViewModel(400, "Model Is Not Valid");
        }
        using (DigiTebDBContext db = new DigiTebDBContext())
        {
            using (var Transaction = db.Database.BeginTransaction())
            {
                try
                {
                    var user = new ApplicationUser()
                    {
                        UserName = model.UserName,
                        Email = model.Email
                        ,
                        CreateTimeStamp = DateTime.Now,
                        LastModifiedTimeStamp = DateTime.Now
                    };
                    IdentityResult result = UserManager.Create(user, model.Password);

                    if (!result.Succeeded)
                        throw new Exception(((string[])result.Errors)[0]);
                    UserUtility.AssignRoleToUser(user.Id, "Operator");
                    var Account = new AspNetUserAccount
                    {
                        AccountTypeValue = AccountType.Demo,
                        CreateTimeStamp = DateTime.Now
                    ,
                        CreateUserId = user.Id,
                        CurrentUserCount = 0,
                        MaxUserCount = 1,
                        IsMultiUser = false
                    ,
                        ExpiryDate = DateTime.Now,
                        LastModifiedUserId = user.Id,
                        LastModifiedTimeStamp = DateTime.Now
                    };
                    AccountRepository.Insert(Account);
                    UnitOfWork.Save();

                    Transaction.Commit();
                    return new ResultViewModel(200, "Registeration was successfull");
                }
                catch(Exception ex)
                {
                    Transaction.Rollback();
                    return new ResultViewModel(400, ex.Message);
                }
                finally
                {
                    UnitOfWork.Dispose();
                }

            }
        }

我的问题是我的 Repository (AccountRepository) 和 UnitOfWork (UnitOfWork) 对象在永远不会被调用的构造函数中被实例化和初始化当一个动作被调用时(无论如何)只有无参数的构造函数被调用,而不是我想要的构造函数只有一个参数。

如何更改它以便调用所需的构造函数而不是默认的无参数构造函数,换句话说 如何确定在 mvc web api 中调用操作时调用的是哪个构造函数?

我搜索了一下,发现我可以使用 DI 来解决这个问题,我使用了 Ninject,但我不知道我应该如何以及在哪里编写我的代码 (使用 Ninject)来更改我的Account 类(控制器)的默认构造函数并将其设置为另一个构造函数

这是我在 NinjectWebCommon.cs 文件夹中的 App_Start 中的 Ninject 修改

 private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind(typeof(IRepository<AspNetUserAccount>)).To(typeof(Repository<AspNetUserAccount>)).InRequestScope();
        kernel.Bind(typeof(IDataContext)).To(typeof(DigiTebDBContext)).InRequestScope();

        kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork)).InRequestScope();

        kernel.Bind<HttpContext>().ToMethod(ctx => HttpContext.Current).InTransientScope();
    }        

提前致谢

【问题讨论】:

  • 框架的默认控制器工厂使用无参数构造函数。查找DependencyResolver

标签: asp.net-mvc asp.net-web-api constructor unit-of-work irepository


【解决方案1】:

我自己从这个链接MVC 4 Web Api Controller does not have a default constructor?找到了答案

首先应该从 Nuget 安装 WebApiContrib.IoC.Ninject,然后应该像下面这样修改 NinjectWebCommon.cs 函数中的 CreateKernel

private static IKernel CreateKernel()
{
var kernel = new StandardKernel();

try
{
    kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
    kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

    RegisterServices(kernel);

    //Note: Add the line below:
    GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);

    return kernel;
}
catch
{
    kernel.Dispose();
    throw;
}
}

通过这样做,当我在控制器中注释默认的无参数构造函数时,DI(在本例中为 ninject)识别替代构造函数(在本例中为具有一个参数的构造函数)本身

【讨论】:

    猜你喜欢
    • 2013-03-13
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多