使模型绑定适用于没有默认构造函数的模型

Nik*_*kos 4 asp.net-mvc model

我一直试图找到一种方法,让模型绑定继续使用带有参数的构造函数的模型.

那个行动:

 [HttpPost]
        public ActionResult Create(Company company, HttpPostedFileBase logo)
        {
            company.LogoFileName = SaveCompanyLogoImage(logo);
            var newCompany = _companyProvider.Create(company);
            return View("Index",newCompany);
        }
Run Code Online (Sandbox Code Playgroud)

和模型

public  Company(CustomProfile customProfile)
        {
            DateCreated = DateTime.Now;
            CustomProfile = customProfile;
        }
Run Code Online (Sandbox Code Playgroud)

我做了我的研究,似乎我需要搞乱我的ninjectControllerfactory:

  public class NinjectControllerFactory : DefaultControllerFactory
    {
        private readonly IKernel ninjectKernel;

        public NinjectControllerFactory()
        {
            ninjectKernel = new StandardKernel();
            AddBindings();
        }

        protected override IController GetControllerInstance(RequestContext requestContext,
                                                             Type controllerType)
        {
            return controllerType == null
                       ? null
                       : (IController) ninjectKernel.Get(controllerType);
        }

        private void AddBindings()
        {
            ninjectKernel.Bind<IAuthProvider>().To<FormsAuthProvider>();
            ninjectKernel.Bind<IMembershipProvider>().To<MembershipProvider>();
            ninjectKernel.Bind<ICustomProfileProvider>().To<CustomProfileProvider>();
            ninjectKernel.Bind<ICompanyProvider>().To<CompanyProvider>();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我也觉得我需要修改我的模型绑定器,但我不清楚前进的方向:

 public class CustomProfileModelBinder : IModelBinder
{
    private const string sessionKey = "CustomProfile";

    #region IModelBinder Members

    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext)
    {
        // get the Cart from the session 
        var customProfile = (CustomProfile) controllerContext.HttpContext.Session[sessionKey];
        // create the Cart if there wasn't one in the session data
        if (customProfile == null)
        {
            customProfile = new CustomProfile("default name");
            controllerContext.HttpContext.Session[sessionKey] = customProfile;
        }
        // return the cart
        return customProfile;
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

希望这能解释我的问题,如果这是一个相当冗长的问题,我很抱歉!

谢谢你的帮助

Dan*_*.G. 8

在这种情况下,似乎必须从会话中获取您需要创建的参数(CustomProfile).然后,您可以使用从默认模型绑定器派生的Company模型的特定模型绑定器,仅更改它创建Company类实例的方式(然后它将以与默认类型相同的方式填充属性):

public class CompanyModelBinder: DefaultModelBinder
{
    private const string sessionKey = "CustomProfile";

    protected override object CreateModel(ControllerContext controllerContext,
                                         ModelBindingContext bindingContext,
                                         Type modelType)
    {
        if(modelType == typeOf(Company))
        {
            var customProfile = (CustomProfile) controllerContext.HttpContext.Session[sessionKey];
            // create the Cart if there wasn't one in the session data
            if (customProfile == null)
            {
                customProfile = new CustomProfile("default name");
                controllerContext.HttpContext.Session[sessionKey] = customProfile;
            }

            return new Company(customProfile);
        }
        else
        {
            //just in case this gets registered for any other type
            return base.CreateModel(controllerContext, bindingContext, modelType)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您只需将此绑定器注册到Company类型,方法是将其添加到global.asax Application_Start方法:

ModelBinders.Binders.Add(typeOf(Company), CompanyModelBinder);
Run Code Online (Sandbox Code Playgroud)

另一种选择可能是通过继承DefaultModelBinder来使用Ninject依赖项创建依赖性感知模型绑定器(因为您使用的是Ninject,它知道如何构建具体类型的实例而无需注册它们).但是,您需要配置一个在Ninject中构建CustomProfile的自定义方法,我相信您可以使用ToMethod().为此您将提取您将在控制器工厂外提取Ninject内核的配置:

public static class NinjectBootStrapper{
    public static IKernel GetKernel()
    {
        IKernel  ninjectKernel = new StandardKernel();
        AddBindings(ninjectKernel);
    }

    private void AddBindings(IKernel ninjectKernel)
    {
        ninjectKernel.Bind<IAuthProvider>().To<FormsAuthProvider>();
        ninjectKernel.Bind<IMembershipProvider>().To<MembershipProvider>();
        ninjectKernel.Bind<ICustomProfileProvider>().To<CustomProfileProvider>();
        ninjectKernel.Bind<ICompanyProvider>().To<CompanyProvider>();
        ninjectKernel.Bind<CustomProfile>().ToMethod(context => /*try to get here the current session and the custom profile, or build a new instance */ );
    }
}

public class NinjectControllerFactory : DefaultControllerFactory
{
    private readonly IKernel ninjectKernel;

    public NinjectControllerFactory(IKernel kernel)
    {
        ninjectKernel = kernel;
    }

    protected override IController GetControllerInstance(RequestContext requestContext,
                                                         Type controllerType)
    {
        return controllerType == null
                   ? null
                   : (IController) ninjectKernel.Get(controllerType);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将创建此模型绑定器:

public class NinjectModelBinder: DefaultModelBinder
{
    private readonly IKernel ninjectKernel;

    public NinjectModelBinder(IKernel kernel)
    {
        ninjectKernel = kernel;
    }

    protected override object CreateModel(ControllerContext controllerContext,
                                         ModelBindingContext bindingContext,
                                         Type modelType)
    {
        return ninjectKernel.Get(modelType) ?? base.CreateModel(controllerContext, bindingContext, modelType)
    }
}
Run Code Online (Sandbox Code Playgroud)

你会将global.asax更新为:

IKernel kernel = NinjectBootStrapper.GetKernel();
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));
ModelBinders.Binders.DefaultBinder = new NinjectModelBinder(kernel);
Run Code Online (Sandbox Code Playgroud)

  • 感谢昆腾!我的意思是Ninject知道如何解决具体类(即没有抽象类或接口)而不注册它们,只要它们具有无参数构造函数或其依赖性也可以解析.例如,您不需要像Bind <Foo>()那样注册绑定.只要Foo具有无参数构造函数或其依赖关系也可以解析为<Foo>(). (2认同)