3

我想为 ASP.NET MVC 编写一个模型绑定器,它将更正用户可见的值。也许它会将值的首字母大写,修剪字符串等。

我想将此行为封装在模型绑定器中。

例如这里是一个TrimModelBinder修剪字符串。(取自这里)

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, 
                          propertyDescriptor, value);
    }
  }

这会将值设置到模型中,但是当页面重新显示时,原始值将保持不变(因为它们处于 ModelState 中)。

我只想将修剪后的值重新显示给用户。

有很多方法可以覆盖 - 比如OnPropertyValidatedOnPropertyValidating等等。

我可能可以让它工作,但如果我覆盖错误的方法,我不想产生一些意想不到的副作用。

当我生成视图时,我宁愿不尝试执行 Trim() 或任何逻辑。我想将这个逻辑完全封装在模型绑定器中。

4

2 回答 2

2

替换这个类。

  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);
    }
  }

编辑:由西蒙修改

(原来有空引用异常并添加了支持分层模型的更改)

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);
        }
    }
于 2010-01-24T11:43:03.910 回答
0

从模型绑定器中,您可以访问ModelBindingContext. 在您可以访问的地方ModelState,您应该能够将该字典中的值修改为修剪后的值。

也许是这样的:

string trimmedValue = GetTheTrimmedValueSomehow();
modelBindingContext.ModelState[modelBindingContext.ModelName] = trimmedValue;
于 2010-01-18T03:16:48.500 回答