標籤:
一、建立自訂模型繫結器:
利用請求資料塑造模型對象並將對象傳遞給動作參數的過程稱為模型繫結(Model Binding)。
大多數時候動作參數是對象的主鍵或其他唯一識別碼,因此我們可以不必在所有的動作中都放置一段重複的資料存取碼(下面代碼“\\Before”部分),而是使用一個自訂的模型繫結器(下面代碼“\\After”部分)。它能夠在動作執行之前載入儲存物件,於是動作不再以唯一識別碼而是以持久化的物件類型作為參數。
// Beforepublic ViewResult Edit (Guid id){ var profile=_profileRepository.GetById(id); return View(new ProfileEditModel(profile)); }// Afterpublic ViewResult Edit (Profile id){ return View(new ProfileEditModel(id)); }
MVC的可擴充性允許我們註冊模型繫結器,這是通過為某一模型類型指定應該使用的綁定器來實現的。但是在實體比較多的情況下,比較理想的情況是我們只對一個公用基底類型(Common Base Type)的自訂模型繫結器進行一次註冊或者讓每個自訂綁定器自己決定是否應該綁定。為了實現這一功能我們需要同時提供自訂模型繫結器提供器和自訂模型繫結器。提供器是由MVC架構使用的以決定使用哪一個模型繫結器進行模型繫結。
為了實現一個自訂模型繫結器提供器,我們需要實現IModelBinderProvider介面:
public interface IModelBinderProvider{ IModelBinder GetBinder(Type modelType) }
任何想要運用自訂匹配邏輯的IModelBinderProvider的實現只需要檢測傳過來的模型類型,並判斷能否返回自訂模型繫結器執行個體。
自訂模型繫結器提供器的一個實現:
public class EntityModelBinderProvider:IModelBinderProvider{ public IModelBinder GetBinder(Type modelType) { if(!typeof(Entity).IsAssignable(modelType)) return null; return new EntityModelBinder(); }}
上例中我們首先檢查modelType參數是否繼承於Entity,如果不是則返回null表明該模型繫結器提供器不能為這一給定的類型提供模型繫結器,反之則返回一個EntityModelBinder(實體模型繫結器)的新執行個體。
完整的模型繫結器需要實現IModelBinder介面:
public class EntityModelBinder:IModelBinder{ public object BindModel( ControllerContext controllerContext, ModelBinderContext bindingContext) { ValueProviderResult value= bindingContext.ValueProvider .GetValue(bindingContext.ModelName); if(value==null) return null; if(string.IsNullOrEmpty(value.AttemptedValue)) return null; int entityId; if(!int.TryParse(value.AttemptedValue,out entityId)) { return null; } Type repositoryType=typeof(IRepository<>) .MakeGenericType(bindingContext.ModelType); var repository=(IRepository)ServiceLocator .Resolve(repositoryType); Entity entity=repository.GetById(entityId); return entity; }}
public interface IRepository<TEntity> where TEntity:Entity{ TEntity Get(int id);}
註冊自訂模型繫結器提供器:
protected void Application_Start(){ ModelBinderProviders.BinderProviders .Add(new EntityModelBinderProvider());}
二、使用自訂值提供器:
通過建立額外的自訂值提供器我們可以進一步消除控制器範文動作中的查詢代碼:
// Beforepublic ViewResult LogOnWidget(LogOnWidgetModel model){ bool inAuthenticated=Request.IsAuthenticated; model.IsAuthenticated=isAuthenticated; model.CurrentUser=Session[""]; return View(model);}// Afterpublic ViewResult LogOnWidget(LogOnWidgetModel model){ bool inAuthenticated=Request.IsAuthenticated; model.IsAuthenticated=isAuthenticated; return View(model);}
我感覺還是暫且略過吧,搞不懂。。。
《ASP.NET MVC 4 實戰》學習筆記 11:模型繫結器與值提供器