Asp.net-Mvc

自定義模型綁定器不驗證模型

  • December 17, 2014

我開始使用 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;
   }
}

更多資訊

引用自:https://stackoverflow.com/questions/8668869