Creating model binding for a model without a default constructor

I am trying to understand how to bind a model to a model with a constructor with arguments.

act:

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

and model

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

I did my research and it looks like I need to mess 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 that I need to change my connecting device, but I do not know how to move on:

  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 problem, sorry if this is a pretty long question!

Thanks for any help

+4
source share
1 answer

In this case, it seems that the parameter that needs to be created (CustomProfile) should be taken from the session. Then you can use a specific connecting device for the company model, which comes from the default connecting object, changing only the method of creating an instance of the Company class (it will then fill in the properties in the same way as by default):

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

You register this binder only for the type of company by adding it to the global.asax Application_Start method:

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

Another option would be to create a dependency model using Ninject dependencies, inheriting from DefaultModelBinder (since you use Ninject, it knows how to instantiate specific types without having to register them). However, you will need to set up a custom method that creates a CustomProfile in a Ninject, which I assume you can use with ToMethod (). To do this, you will extract the extraction of your Ninject kernel configuration outside the factory controller:

 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 this case, you will create this connecting device:

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

And you should update global.asax as:

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

Source: https://habr.com/ru/post/1448016/


All Articles