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



我一直在试图找到一种方法,让模型绑定到一个带有参数的构造函数的模型。

动作:

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

我已经做了研究,似乎我需要处理我的项目控制器工厂:

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

我也觉得我需要修改我的模型活页夹,但我不清楚前进的道路:

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
}

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

感谢提供的任何帮助

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

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方法,您将仅为公司类型注册此活页夹:

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

另一种选择是通过从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);
}
}

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

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更新为:

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

最新更新