程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> Asp.net MVC示例項目“Suteki.Shop”分析之ModelBinder

Asp.net MVC示例項目“Suteki.Shop”分析之ModelBinder

編輯:關於ASP.NET

在Suteki.Shop中,作者構造了一個ModelBinder基類“DataBinder”,其本身繼承自 IModelBinder接口,並以此其類派生出其它一些子類類如ProductBinder等等。可以說除了極個別的地方 之外,DataBinder被用於了Suteki.Shop大多數的ModelBinder綁定場景之路。

首先看一下其類圖 結構:

作為基類, DataBinder(圖中左下方)實現了將HTTP請求過來的數據轉換成為模型中相應的類型。其核心方法就是 BindModel,下面做一下解釋說明:

public virtual object BindModel(ControllerContext controllerContext,  ModelBindingContext bindingContext)
{
object entity;

if (declaringAttribute == null || declaringAttribute.Fetch)
{
entity =  FetchEntity(bindingContext, controllerContext);
}
else
{
entity =  Activator.CreateInstance(bindingContext.ModelType);
}

try
{
validatingBinder.UpdateFrom(entity,  controllerContext.HttpContext.Request.Form, bindingContext.ModelState,  bindingContext.ModelName);
}
catch(ValidationException ex)
{
//Ignore validation exceptions - they are stored in ModelState.
//The  controller can access the errors by inspecting the ModelState dictionary.
}

return entity;
}

首先要說明的就是declaringAttribute,這個變 量其實是DataBindAttribute類型實例,其作用是判斷當前所請求過來的數據是用於創建新的Model信息 還是獲取並綁定已有的數據記錄。該實例的實始化是交給Accept方法來實現的(注意Accept方法的聲明 是在IAcceptsAttribute接口中定義的):

public void Accept(Attribute attribute)
{
declaringAttribute =  (DataBindAttribute) attribute;
}

而對該方法的調用是放在了 BindUsingAttribute的GetBinder()方法中,所以這裡要先看一下BindUsingAttribute的具體實現:

public class BindUsingAttribute : CustomModelBinderAttribute
{
private readonly Type binderType;

public BindUsingAttribute(Type  binderType)
{
if(!typeof(IModelBinder).IsAssignableFrom(binderType))
{
throw new InvalidOperationException("Type '{0}' does not implement  IModelBinder.".With(binderType.Name));
}

this.binderType =  binderType;
}

public override IModelBinder GetBinder()
{
var  binder = (IModelBinder) ServiceLocator.Current.GetInstance(binderType);

if (binder is IAcceptsAttribute)
{
((IAcceptsAttribute)binder).Accept(this);
}

return binder;
}
}

這個屬性類也就是在Action中進行 ModelBinder綁定時用到的,其類構造方法中通過一個類型參數初始化並在GetBinder()方法中使用 ServiceLocator來進行最終的ModelBinder實例化構建,注意在該方法中有對當前binder的邏輯判斷 (IAcceptsAttribute),並以此來區別當前Action綁定的ModelBinder是否實現了IAcceptsAttribute接口 。如果沒實現或declaringAttribute.Fetch為true時,就會在之前的DataBinder類方法 “BindModel”中調用“FetchEntity()”方法,FetchEntity會從提交的數據中的主鍵(PrimaryKey)中檢索數據並返回該對象實例,代碼如下:

private object FetchEntity(ModelBindingContext bindingContext,  ControllerContext controllerContext)
{
object entity;
var primaryKey =  bindingContext.ModelType.GetPrimaryKey();//從Shop.dbml中查找相應的主鍵信息
string  name = bindingContext.ModelName + "." + primaryKey.Name;//拼接出要獲取的主 鍵名稱

string rawKeyValue = controllerContext.HttpContext.Request.Form [name];

if (string.IsNullOrEmpty(rawKeyValue))
{
throw new  InvalidOperationException("Could not find a value named '{0} '".With(name));
}

int key = Convert.ToInt32(rawKeyValue);
var repository = resolver.GetRepository(bindingContext.ModelType);
entity =  repository.GetById(key);
return entity;
}

注意上面代碼中的這兩行:

var repository = resolver.GetRepository(bindingContext.ModelType);
entity = repository.GetById(key);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved