ASP.net MVC - Model binding excludes class fields?

前端 未结 2 1441
余生分开走
余生分开走 2020-11-29 13:06

In a recent project - i\'ve hit an unexpected snag.
A class with simple public fields (note not properties) doesn\'t seem to want to play nice with the ASP.net MVC 3.0

2条回答
  •  半阙折子戏
    2020-11-29 14:03

    I know it's against the c# team's philosophy, but I think fields are clean in poco classes. Seems like less moving parts to me. Anyway,

    Here's a model binder that will load fields. It's fairly trivial. Note that you can use a new object with Activator.CreateInsance or start with an existing object as a starting point. I was using Yes/No dropdowns for bool, you may have check boxes, in which case unfortunately you'll have to loop through fieldinfos and look for missing form inputs b/c html doesn't submit form items if it's a false checkbox.

    ~/Binders/FieldModelBinder.cs

    using System;
    using System.Reflection;
    using System.Web.Mvc;
    
    namespace MyGreatWebsite.Binders
    {
      public class FieldModelBinder : DefaultModelBinder
      {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
          var obj = controllerContext.HttpContext.Session["CurrentObject"];// Activator.CreateInstance(bindingContext.ModelType);
          var form = controllerContext.HttpContext.Request.Form;
          foreach (string input in form)
          {
            FieldInfo fieldInfo = obj.GetType().GetField(input);
            if (fieldInfo == null)
              continue;
            else if (fieldInfo.FieldType == typeof(bool))
              fieldInfo.SetValue(obj, form[input] == "Yes");
            else
              fieldInfo.SetValue(obj, Convert.ChangeType(form[input], fieldInfo.FieldType));
          }
          return obj;
        }
      }
    }
    

    Startup.cs

      public partial class Startup
      {
        public void Configuration(IAppBuilder app)
        {
          ConfigureAuth(app);
          ModelBinders.Binders.Add(typeof(FieldModelBinder), new FieldModelBinder());
        }
      }
    

    Usage

    [HttpPost]
    public ActionResult MyGreatAction([ModelBinder(typeof(FieldModelBinder))] MyGreatProject.MyGreatNamespace.MyGreatType instance, string myGreatParameters)
    {
      DoSomethingGreatWithMyInstance();
      return View();
    }
    

提交回复
热议问题