Asp.net-Mvc
自定義模型綁定器不驗證模型
我開始使用 knockout.js,並在此過程中使用了 FromJsonAttribute(由 Steve Sanderson 創建)。我遇到了自定義屬性未執行模型驗證的問題。我整理了一個簡單的例子——我知道它看起來像很多程式碼——但基本問題是如何在自定義模型綁定器中強制驗證模型。
using System.ComponentModel.DataAnnotations; namespace BindingExamples.Models { public class Widget { [Required] public string Name { get; set; } } }這是我的控制器:
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唯一綁定到模型並且確實,就像你說的那樣,沒有驗證。您可以向 中添加驗證,以
FromJsonAttribute根據他的 DataAnnotations 屬性驗證模型。這可以使用
TypeDescriptor類來完成。TypeDescriptor提供有關組件特徵的資訊,例如其屬性、屬性和事件。
查看我的解決方案。我已經測試過了。
解決方案
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; } }更多資訊