在我的MVC 3解决方案中,我希望将查询字符串中的所有ID都加密。要解密我从DefaultModelBinder继承并覆盖BindProperty方法的URL:
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;
}
之后我在Application_Start上的global.asax中设置了新的DefaultBinder:
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 :(得分:2)
如果您的模型当然没有Id属性,则不会调用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);
}