asp.net-mvc - 自定义模型绑定(bind)器不验证模型

标签 asp.net-mvc json data-annotations custom-model-binder

我开始使用 knockout.js,并在此过程中使用了 FromJsonAttribute(由 Steve Sanderson 创建)。我遇到了自定义属性未执行模型验证的问题。我整理了一个简单的例子——我知道它看起来像很多代码——但基本问题是如何在自定义模型绑定(bind)器中强制验证模型。

using System.ComponentModel.DataAnnotations;

namespace BindingExamples.Models
{
    public class Widget
    {
        [Required]
        public string Name { get; set; }
    }
}

这是我的 Controller :
using System;
using System.Web.Mvc;
using BindingExamples.Models;

namespace BindingExamples.Controllers
{
    public class WidgetController : Controller
    {

        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(Widget w)
        {
            if(this.ModelState.IsValid)
            {
                TempData["message"] = String.Format("Thanks for inserting {0}", w.Name);
                return RedirectToAction("Confirmation");
            }
            return View(w);
        }

        [HttpPost]
        public ActionResult PostJson([koListEditor.FromJson] Widget w)
        {
            //the ModelState.IsValid even though the widget has an empty Name
            if (this.ModelState.IsValid)
            {
                TempData["message"] = String.Format("Thanks for inserting {0}", w.Name);
                return RedirectToAction("Confirmation");
            }
            return View(w);
        }

        public ActionResult Confirmation()
        {
            return View();
        }

    }
}

我的问题是模型在我的 PostJson 方法中始终有效。 为了完整起见,这里是 FromJson 属性的 Sanderson 代码:
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace koListEditor
{
    public class FromJsonAttribute : CustomModelBinderAttribute
    {
        private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();

        public override IModelBinder GetBinder()
        {
            return new JsonModelBinder();
        }

        private class JsonModelBinder : IModelBinder
        {
            public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
                if (string.IsNullOrEmpty(stringified))
                    return null;
                var model = serializer.Deserialize(stringified, bindingContext.ModelType);
                return model;
            }
        }
    }
}

最佳答案

描述
FromJsonAttribute只绑定(bind)到模型,就像你说的那样,没有验证。

您可以将验证添加到 FromJsonAttribute为了根据他的 DataAnnotations 属性验证模型。

这可以使用 TypeDescriptor 来完成。类(class)。

TypeDescriptor Provides information about the characteristics for a component, such as its attributes, properties, and events.



查看我的解决方案。我已经测试过了。

解决方案
private class JsonModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
        if (string.IsNullOrEmpty(stringified))
            return null;
        var model = serializer.Deserialize(stringified, bindingContext.ModelType);

        // DataAnnotation Validation
        var validationResult = from prop in TypeDescriptor.GetProperties(model).Cast<PropertyDescriptor>()
                                from attribute in prop.Attributes.OfType<ValidationAttribute>()
                                where !attribute.IsValid(prop.GetValue(model))
                                select new { Propertie = prop.Name, ErrorMessage = attribute.FormatErrorMessage(string.Empty) };

        // Add the ValidationResult's to the ModelState
        foreach (var validationResultItem in validationResult)
            bindingContext.ModelState.AddModelError(validationResultItem.Propertie, validationResultItem.ErrorMessage);

        return model;
    }
}

更多信息
  • TypeDescriptor Class
  • System.ComponentModel.DataAnnotations Namespace
  • 关于asp.net-mvc - 自定义模型绑定(bind)器不验证模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8668869/

    相关文章:

    asp.net-mvc - Razor DropDownListFor : Adding Extra Attribute To SelectList Option Tag

    asp.net-mvc - 将ajax post的返回数据转移到隐藏? ASP.NET MVC

    java - 如何在java中处理嵌套在数组中的JSON数组

    c# - 序列化为 XML 时如何处理 JSON 键中的空格?

    asp.net-mvc - 为什么 StringLength 不能与 ASP.NET MVC 非侵入式验证一起使用?

    c# - WebApi POST 不包含 ID 字段

    asp.net-mvc - 将 DataAnnotation 属性从 Model 应用到 ViewModel

    html - 如何让我的 ul 样式只适用于一个类

    c# - 密码必须至少有一个非字母字符

    node.js - 有效存储数据,经常访问并且不经常更改