2011-11-04 132 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之前。再次感谢! –