ASP.NET MVC5 ModelBinder


什么是ModelBinding

ASP.NET MVC中,所有的請求最終都會到達某個Controller中的某個Action並由該Action負責具體的處理和響應。為了能夠正確處理請求,Action的參數(如果有的話),必須在Action執行之前,根據相應的規則,把請求中所包含的數據提取出來並將映射為Action的參數值,這個過程就是ModelBinding。ModelBinding的作用就是為Action提供參數列表。

ModelBinding的好處

  1. 使代碼變得更加簡潔
  2. 幫助我們獲取HTTP請求中的數據
  3. 幫助我們完成必要的數據類型轉換

ASP.NET MVC中ModelBinding的實現過程

ASP.NET MVC中ModelBinding的實現過程比較復雜,這里簡要說明它的總體流程。具體的實現過程可以看蔣金楠的《ASP.NET MVC5框架揭秘》或者看他的博客How ASP.NET MVC Works?,講解很詳細。


 
  • HTTP請求中的數據可能存在於querystring中,也可能在表單中,也有可能是JSON字符串。究竟從哪里獲取數據,這要依賴於參數的描述信息ParameterDescriptor
  • ParameterDescriptor的獲取需要借助於ControllerDescriptorActionDescriptor,它們分別用來描述Controller和Action
  • IModelBinderProvider用於提供合適的ModelBinder對象,我們可以自己實現該接口以獲取自定義的IModelBinder
  • ModelBinding的核心IModelBinder,默認實現類是DefaultModelBinder,我們可以自己實現IModelBinder接口來擴展ModelBinder
  • IValueProvider針對不同的數據源提供了數據的訪問機制
  • ValueProviderResult提供了兩個ConvertTo方法重載以實現向指定目標類型的轉換。
  • 經過上述一系列的處理獲取最終結果

自定義ModelBinder

自定義Modelbinder只需實現System.Web.Mvc.IModelBinder接口即可。這里需要注意一點,System.Web.ModelBinding命名空間下也有一個IModelBinder接口,不要搞錯了。

public class LessonEditInfoViewModelBinder : IModelBinder
{
    //根據前台傳遞的id值獲取對象
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var idStr = controllerContext.HttpContext.Request["id"] ?? controllerContext.RouteData.Values["id"]?.ToString();
        int id = 0;
        if (!int.TryParse(idStr, out id))
        {
            return null;
        }
        var model = new LessonBLL().GetLessonEditInfo(id);
        return model;
    }
}

然后使用ModelBinderAttribute進行標注即可:

/*
    根據前台傳遞的id值解析出對象數據,Action無需關注對象的獲取,使代碼變得清晰簡潔
*/
public ActionResult Edit([ModelBinder(typeof(LessonEditInfoViewModelBinder))]LessonEditInfoViewModel lesson)
{
    if (lesson == null)
    {
        //跨控制器的視圖跳轉要使用視圖的路徑+文件名
        return View("/Views/Exception/GenericError.cshtml", new ExceptionViewModel { Title = "404", Description = "課程不存在!" });
    }
    return View(lesson);
}

如果項目中多處需要使用自定義的ModelBinder,那么再使用ModelBinderAttribute進行標注就不大合適了。這種情況我們可以使用自定義的ModelBinderProvier。代碼如下:

public class CustomeModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(Type modelType)
    {
        if (modelType == typeof(LessonEditInfoViewModel))
        {
            return new LessonEditInfoViewModelBinder();
        }
        return null;
    }
}

然后將自定義的ModelBinderProvider注冊到ASP.NET MVC系統中

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        ModelBinderProviders.BinderProviders.Insert(0, new CustomeModelBinderProvider());
    }
}

完成上述兩步之后,就無需使用ModelBuilderAttribute進行標注了。

除此之外,還可在Global文件中使用使用ModelBinder類的Binder屬性來注冊ModelBinderProvider

ModelBinders.Binders.Add(typeof(LessonEditInfoViewModel),new LessonEditInfoViewModelBinder());

不同的ModelBinder提供策略有不同的優先級,具體如下:

  1. 在參數上使用CustomModelBinderAttribute
  2. 使用ModelBinderProviders.BinderProviers
  3. 使用ModelBinders.Binders
  4. 參數類型上標記CustomModelBinderAttribute
  5. ASP.NET MVC中提供的DefaultModelBinder

注意,CustomModelBinderAttribute是抽象類,在ASP.NET MVC中有唯一子類ModelBinderAttribute。

參考文章:

Model Binders in ASP.NET MVC
ModelBinder——ASP.NET MVC Model綁定的核心
ASP.NET MVC以ValueProvider為核心的值提供系統
玩轉Asp.net MVC 的八個擴展點
ASP.NET MVC中你必須知道的13個擴展點

版權聲明

本文為作者原創,版權歸作者雪飛鴻所有。 轉載必須保留文章的完整性,且在頁面明顯位置處標明原文鏈接

如有問題, 請發送郵件和作者聯系。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM