【问题标题】:MVC 5 Model Binder OverrideMVC 5 模型绑定器覆盖
【发布时间】:2016-03-23 17:39:41
【问题描述】:

我写了一个模型绑定器的覆盖。

public override object BindModel(Controller context, ModelBindingContext bindingContext)
{
    var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

    object returnVal = null;

    if (value == null)
        returnVal = base.BindModel(controllerContext, bindingContext);
    else
    {
        /* custom logic here that never seems to get called.
            returnVal = something();
        */
    }

    return returnVal;
}

我还有一个 javascript 服务(在 Angular 中),它向我的一个控制器发出 AJAX 请求。

AJAX 请求尝试发布整数集合。我尝试单步执行模型活页夹,似乎value 始终为空。通过某种魔法,base.BindModel() 仍然能够将我的集合绑定到正确的 C# 对象。

这个问题是我不能使用我的自定义活页夹,因为else 块永远不会被调用。除了使用ValueProvider之外,我还有其他方法可以获得价值吗?

我也相信在这个自定义活页夹正常工作之前(根据记忆可能是错误的)。我最近从 4.5 更新到 5.2.something。是否有任何更新可以改变这种行为?

【问题讨论】:

    标签: c# ajax asp.net-mvc


    【解决方案1】:

    我还有一个 javascript 服务(在 Angular 中),它向我的一个控制器发出 AJAX 请求。

    ...

    这个问题是我不能使用我的自定义活页夹,因为 else 块永远不会被调用。

    • 我将假设您已在全局范围内或在一个或多个参数上的操作本身上正确注册了活页夹。
    • 我还假设您的活页夹在您期望的时候被调用。

    它为空,因为它无法根据您尝试绑定的模型名称找到数据。该名称是否可以找到该值取决于模型名称和客户端请求中发送的数据必须对齐/匹配。但是在任何人告诉你为什么它不匹配的数据(包括你的模型和数组)之前可以通过以下三种方式之一从客户端发送:

    1. 如果使用 URL,您将在查询字符串中重复使用相同的属性名称。示例:?myArray=1&myArray=2&myArray=3。这意味着您必须在模型绑定器中考虑这一点。
    2. 如果在 POST 中使用 data(正文),那么它可能是一个实际的数组对象。 json 中的示例:{"myArray":[1,2,3,4]}
    3. 您还可能会序列化整个表单并使用 Angular 发送它(这将允许您更好地使用 MVC 中的绑定功能

    因此,为了更好地回答您的问题,您需要提供

    1. 浏览器发送数据的格式以及发送方式(查询字符串或数据负载中)(这可能在您的 Angular 工厂、服务或控制器中
    2. 您尝试绑定的模型定义

    回顾一下:bindingContext.ModelName 是预期的名称,并且必须与模型绑定器试图查找的数据匹配。如果您发送的是{"myArray":[1,2,3,4]},但您的模型属性名为ProductIds,那么它将始终为空。

    我最近从 4.5 更新到 5.2.something

    不,我不知道。


    最后的想法。您还可以让默认模型绑定器执行,然后在类型匹配时对返回的值执行某些操作。如果现在绑定没有问题,但您想做一些后处理,这将是一个更好的选择。示例:

    public override object BindModel(Controller context, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
    
        object returnVal = base.BindModel(controllerContext, bindingContext);
    
        /* check returnVal and then additional custom logic here */.
        
        return returnVal;
    }
    

    【讨论】:

      【解决方案2】:

      请确保您已执行以下操作:-

      1. 自定义模型绑定:-

        public class HomeCustomDataBinder : DefaultModelBinder
        {
            public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                if (bindingContext.ModelType == typeof(HomePageModels))
                {
                    HttpRequestBase request = controllerContext.HttpContext.Request;
        
                    string title = request.Form.Get("Title");
                    string day = request.Form.Get("Day");
                    string month = request.Form.Get("Month");
                    string year = request.Form.Get("Year");
        
                    return new HomePageModels
                    {
                        Title = title,
                        Date = day + "/" + month + "/" + year
                    };
        
                    //// call the default model binder this new binding context
                    //return base.BindModel(controllerContext, newBindingContext);
                }
                else
                {
                    return base.BindModel(controllerContext, bindingContext);
                }
            }
        
        } 
        
      2. 一旦我们完成了自定义类的编码,我们将需要注册我在 Global.asax 中 Application_Start() 下所做的类。

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
            ModelBinders.Binders.Add(typeof(HomePageModels), new HomeCustomBinder());
        }
        

        3) 最后,我们需要通知控制器我们希望它使用的绑定。我们可以使用属性[ModelBinder(typeof(HomeCustomBinder))] 指定如下:

        [HttpPost]
        public ActionResult Index([ModelBinder(typeof(HomeCustomBinder))] HomePageModels home)
        {
            if (ModelState.IsValid)
            {
                ViewBag.Title = home.Title;
                ViewBag.Date = home.Date;
            }
            return View();
        }
        

      【讨论】:

      • 可以跳过第3步;通过在ModelBinders 列表中注册它,MVC 将隐式地完成这项工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-08
      • 2018-06-18
      相关资源
      最近更新 更多