2011-11-04 121 views
2

在我的MVC 3解決方案中,我希望將查詢字符串中的所有Id都加密。要解密的URL我從DefaultModelBinder繼承和overrided BindProperty方法:自定義模型綁定問題

public class CryptedIdBinder : DefaultModelBinder 
{ 

    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
    { 
     if (propertyDescriptor.Name.ToLower() == "id") 
     { 
      propertyDescriptor.SetValue(bindingContext.Model, CryptoHelper.Decrypt(controllerContext.HttpContext.Request.Form["id"])); 
      return; 
     } 

     base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
     return; 
    } 

之後,我設置在Global.asax的新DefaultBinder上的Application_Start:

System.Web.Mvc.ModelBinders.Binders.DefaultBinder = new CryptedIdBinder(); 

我沒有從IModelBinder繼承,因爲我想更改綁定邏輯只有解決方案中的id字段。

問題是BindProperty方法從不被調用。我錯了什麼?

PS。爲了確保我打電話至少BindModel方法我將我的定製綁定在這個代碼的和平,它是由調試器擊中:

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     return base.BindModel(controllerContext, bindingContext); 
    } 
+0

你可以張貼一些示例模型代碼?也許DefaultModelBinder過濾了你的一些屬性... – nemesv

+0

對不起,我沒有聽到你的想法。它不是一個全球活頁夾,它應該適用於所有型號?此Id參數未在模型中定義 - 它位於默認路線 –

回答

2

如果您的機型沒有,當然標識符屬性BindProperty不會被調用。因爲它調用了模型屬性。如果我理解你的問題,你需要的是轉換每個Id命名查詢字符串參數。在這種情況下,您需要自定義值提供程序而不是模型綁定器。這是關於價值提供者的good article。而且它很容易寫一個:

public class MyValueProviderFacotry : ValueProviderFactory 
{ 
    public override IValueProvider GetValueProvider(ControllerContext controllerContext) 
    { 
     return new MyValueProvider(controllerContext); 
    } 
} 

public class MyValueProvider : IValueProvider 
{ 
    private ControllerContext controllerContext; 

    public MyValueProvider(ControllerContext controllerContext) 
    { 
     this.controllerContext = controllerContext; 
    } 

    public bool ContainsPrefix(string prefix) 
    { 
     return true; 
    } 

    public ValueProviderResult GetValue(string key) 
    { 
     if (key.ToLower() == "id") 
     { 
      var originalValue = controllerContext.HttpContext.Request.QueryString[key]; 
      var transformedValue = CryptoHelper.Decrypt(orignalValue); 
      var result = new ValueProviderResult(transformedValue,originalValue,CultureInfo.CurrentCulture); 
      return result; 
     } 
     return null; 
    } 
} 

在Global.asax中:

protected void Application_Start() 
     { 
      AreaRegistration.RegisterAllAreas(); 
      ValueProviderFactories.Factories.Insert(4, new MyValueProviderFacotry()); //Its need to be inserted before the QueryStringValueProviderFactory 
      RegisterGlobalFilters(GlobalFilters.Filters); 
      RegisterRoutes(RouteTable.Routes); 
     } 
+0

中非常感謝您的答覆。它看起來像這是我正在尋找的東西。我會在早上嘗試這個 –

+0

這個作品幾乎很棒。我必須做的唯一事情就是實現ContainsPrefix(所以它確實返回值,指示是否需要搜索值),並將它放在QueryStringValueProviderFactory之前,但不放在RouteValueProviderFactory之前。再次感謝! –