开发者

How can i use a ModelBinder to correct values that will then be visible to the user?

开发者 https://www.devze.com 2022-12-17 04:12 出处:网络
I want to write a modelbinder for ASP.NET MVC that will correct values that will be visible to the user. Maybe it will capitalize the initial letter of a value, trim strings, etc. etc.

I want to write a modelbinder for ASP.NET MVC that will correct values that will be visible to the user. Maybe it will capitalize the initial letter of a value, trim strings, etc. etc.

I'd like to encapsulate this behavior within a modelbinder.

For instance here is a TrimModelBinder to trim strings. (taken from here)

public class TrimModelBinder : DefaultModelBinder
  {
    protected override void SetProperty(ControllerContext controllerContext, 
      ModelBindingContext bindingContext, 
      System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
      if (propertyDescriptor.PropertyType == typeof(string))
      {
        var stringValue = (string)value;
        if (!string.IsNullOrEmpty(stringValue))
          stringValue = stringValue.Trim();

        value = stringValue;
      }

      base.SetProperty(controllerContext, bindingContext, 
     开发者_C百科                     propertyDescriptor, value);
    }
  }

This will set the values into the model, but when the page is redisplayed the original values will persist (because they're in ModelState).

I'd like to just re-display the trimmed values to the user.

Theres a whole lot of methods to override - like OnPropertyValidated, and OnPropertyValidating etc.

I could probably get it to work, but I don't want to have some unintended side effect if I override the wrong method.

I'd rather not try to do a Trim() or whatever the logic is when I'm generating the view. I want to encapsulate this logic completely within a modelbinder.


Replace this class.

  public class TrimModelBinder : DefaultModelBinder
  {
    protected override void SetProperty(ControllerContext controllerContext,
      ModelBindingContext bindingContext,
      System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
      if (propertyDescriptor.PropertyType == typeof(string))
      {
        var stringValue = (string)value;
        if (!string.IsNullOrEmpty(stringValue))
          stringValue = stringValue.Trim();

        value = stringValue;
        bindingContext.ModelState[propertyDescriptor.Name].Value = 
          new ValueProviderResult(stringValue,
            stringValue,
            bindingContext.ModelState[propertyDescriptor.Name].Value.Culture);
      }

      base.SetProperty(controllerContext, bindingContext,
                propertyDescriptor, value);
    }
  }

Edit: modified by simon

(original had null reference exception and added change to support hierarchical model)

protected override void SetProperty(ControllerContext controllerContext,
    ModelBindingContext bindingContext,
    System.ComponentModel.PropertyDescriptor propertyDescriptor,
    object value)
    {
        string modelStateName = string.IsNullOrEmpty(bindingContext.ModelName) ? propertyDescriptor.Name : 
            bindingContext.ModelName + "." + propertyDescriptor.Name;

        // only process strings
        if (propertyDescriptor.PropertyType == typeof(string))
        {
            if (bindingContext.ModelState[modelStateName] != null)
            {
                // modelstate already exists so overwrite it with our trimmed value
                var stringValue = (string)value;
                if (!string.IsNullOrEmpty(stringValue))
                    stringValue = stringValue.Trim();

                value = stringValue;
                bindingContext.ModelState[modelStateName].Value =
                  new ValueProviderResult(stringValue,
                    stringValue,
                    bindingContext.ModelState[modelStateName].Value.Culture);
            }
            else
            {
                // trim and pass to default model binder
                base.SetProperty(controllerContext, bindingContext, propertyDescriptor, (value == null) ? null : (value as string).Trim());
            }
        }
        else
        {
            base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
        }
    }


From within the model binder you have access to the ModelBindingContext. On that you have access to ModelState and you should be able to modify the values in that dictionary to be the trimmed values.

Maybe something like:

string trimmedValue = GetTheTrimmedValueSomehow();
modelBindingContext.ModelState[modelBindingContext.ModelName] = trimmedValue;
0

精彩评论

暂无评论...
验证码 换一张
取 消