專案建立 DataBinder 基類實作 IModelBinder,派生 ProductBinder、OrderBinder 等,覆蓋絕大多數模型綁定場景。
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) { /* 錯誤已記錄於 ModelState */ }
return entity;
}
private object FetchEntity(ModelBindingContext bindingContext, ControllerContext controllerContext) {
var primaryKey = bindingContext.ModelType.GetPrimaryKey();
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);
return repository.GetById(key);
}
透過 DataBindAttribute 標記 Action 參數決定是新建還是取得既有實體,配合 BindUsingAttribute 從 IOC 解析具體 Binder,實現聲明式模型綁定。