制作模型绑定工作,没有默认构造函数的模型 [英] Making model binding work for a model with no default constructor

查看:114
本文介绍了制作模型绑定工作,没有默认构造函数的模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图找出一种方法,有一个模型结合去与带参数的构造函数的模型。

I’ve been trying to figure a way to have a model-binding go on with a model with a constructor with arguments.

动作:

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

和模型

public  Company(CustomProfile customProfile)
        {
            DateCreated = DateTime.Now;
            CustomProfile = customProfile;
        }

我做我的研究,看来我需要用我的ninjectControllerfactory勾搭:

I've done my research and seems I need to mess around with my 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>();
        }
    }

我也觉得我需要修改我的模型绑定,但我不是在前进的道路明确的:

I also feel I need to modify my model binder but I'm not clear on the way forward:

 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
}

希望这解释了我的问题,我很抱歉,如果它是一个相当长的啰嗦的问题!

Hope this explains my issue, I'm sorry if its a rather long winded question!

感谢您的任何援助

推荐答案

在这种情况下,看来你需要创建(CustomProfile)的参数必须从会议上作出。然后,您可以使用从默认的模型绑定派生,只改变其创建的公司类的一个实例(然后将填充以同样的方式作为默认的属性)的方式,公司模型的特定模型绑定:

In this case it seems that the parameter you need to create (CustomProfile) must be taken from the session. You could then use a specific model binder for the Company model that derives from the default model binder, changing only the way it creates an instance of the Company class (it will then populate the properties in the same way as the default one):

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

您将通过添加这在Global.asax Application_Start方法中注册该粘合剂仅用于公司类型:

You will register this binder only for the Company type by adding this to the global.asax Application_Start method:

ModelBinders.Binders.Add(typeOf(Company), CompanyModelBinder);

另一个选择可能是从DefaultModelBinder继承创建使用Ninject的依赖关系的依赖感知模型粘合剂(如你正在使用Ninject,它知道如何构建具体类型的实例,而无需注册人)。
然而,你将需要配置构建CustomProfile在Ninject,我相信你可以使用ToMethod做()的自定义方法。
为此,您将提取您将提取控制器工厂之外的你Ninject内核配置:

Another option could be to create a dependency-aware model binder using the Ninject dependencies by inheriting from the DefaultModelBinder (As you are using Ninject, it knows how to build instances of concrete types without the need of registering them). However you would need to configure a custom method that builds the CustomProfile in Ninject, which I believe you could do using the ToMethod(). For this you would extract you would extract your configuration of your Ninject kernel outside the controller factory:

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

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

In that case you would create this model binder:

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

和您将更新在Global.asax为:

And you would update the global.asax as:

IKernel kernel = NinjectBootStrapper.GetKernel();
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));
ModelBinders.Binders.DefaultBinder = new NinjectModelBinder(kernel);

这篇关于制作模型绑定工作,没有默认构造函数的模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆