将输入转换为大写的大写属性

时间:2013-07-17 16:05:47

标签: asp.net-mvc custom-attributes data-annotations

我在MVC4中工作,想要使用Uppercase属性定义模型。我们的想法是,大写属性的存在会导致模型值在到达服务器时转换为大写。

目前我在模型中有以下代码:

    [Required]
    [Display(Name="Account Code")]
    [StringValidation(RegExValidation.AccountCode, Uppercase=true)]
    public string Account
    {
        get { return _account; }
        set
        {
            if (value != null)
                _account = value.ToUpper();
        }
    }

但我真正想要的是:

    [Required]
    [Display(Name="Account Code")]
    [StringValidation(RegExValidation.AccountCode)]
    [Uppercase]
    public string Account { get; set; }

我认为我可能需要将“大写”属性创建为ValidationAttribute,以确保在模型到达服务器时触发它。但这似乎有点不对,因为我并没有真正验证数据。还有更好的方法吗?

另外,有没有办法确保属性的调用顺序?我真的想在自定义StringValidation属性触发之前将数据转换为大写,因为这会检查正则表达式模式中文本的大小写。

要为此添加一些背景知识,我希望减少添加代码以大写数据的需要。涅(nirvana)将是一个单一属性,它可以在模型绑定或验证阶段更新进入服务器的数据。然后可以在StringValidation属性中引用此属性以修改其检查中使用的RegEx值。然后我还可以在自定义TextBoxFor辅助方法中查找此属性,以便我可以添加text-transform: uppercase,使其在客户端看起来正确。

有没有人有任何想法?

4 个答案:

答案 0 :(得分:5)

我已经设法让这个工作到了一定程度,所以这是我的解决方案供其他人评估。

需要注意的是,无法获得完整的解决方案,因为我无法在Modelmetadata属性中获得StringValidation.IsValid()。我在这里遇到的具体问题是我可以获取元数据,但是我无法从PropertyName获得DisplayName。有多个选项,但我的某些属性具有相同DisplayName的事实意味着我无法确定ProprtyName是否是我实际验证的那个。

以下是ValidationAttribute的代码:

public class StringValidationAttribute : ValidationAttribute, IClientValidatable, IMetadataAware {

    private bool _uppercase;

    public StringValidationAttribute(bool uppercase = false) {
         _uppercase = uppercase;
    }

    ...

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["Uppercase"] = _uppercase;
    }
}

然后我创建了一个新的IModelBinder实现:

public class StringBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {           
        ValueProviderResult result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (result == null)
            return null;

        if (bindingContext.ModelMetadata.AdditionalValues.ContainsKey("Uppercase")) {
            if ((bool)bindingContext.ModelMetadata.AdditionalValues["Uppercase"]])
                return result.AttemptedValue.ToUpper();
        }

        return result.AttemptedValue;
    }
}

并在我的Global.asax文件中注册:

ModelBinders.Binders.Add(typeof(string), new StringBinder());

到目前为止的代码将导致进入MVC的任何字符串输入转换为大写,如果它在模型上附加了StringValidationAttribute,并且已经设置了大写指示符。

接下来,为了实现我将html表单设为大写的愿望,我实现了一个名为EditorTemplate的新string.cshtml。在这个视图中我添加了:

RouteValueDictionary htmlAttributes = new RouteValueDictionary();
if ((bool)ViewData.ModelMetadata.AdditionalValues["Uppercase"]) {
    htmlAttributes.Add("class", "Uppercase");
}
@Html.TextBox("", Model, htmlAttributes)

将CSS作为;

.Uppercase {
    text-transform: uppercase;
}

希望这篇文章可以帮助其他人。

答案 1 :(得分:2)

对于Web API,最好将传入的json转换为大写或小写。

    public class ToUpperCase : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(string);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return reader.Value.ToString().ToUpper();
        }            
    }



    [Display(Name = "PNR NAME")]
    [JsonConverter(typeof(Annotations.ToUpperCase))]
    public string PNR { get; set; }

或全球;

  protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        //.......... others



        JsonMediaTypeFormatter jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
        JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings();
        jSettings.Converters.Add(new UpperCaseStringConverter());
        jsonFormatter.SerializerSettings = jSettings;
    }

答案 2 :(得分:0)

你是对的,ValidationAttribute不合适。看起来在模型绑定阶段这样做会是一个更好的主意。有关如何自定义此行为的详细说明,请参阅this article

根据那里提供的信息,我相信您应该可以基于CustomModelBinderAttribute创建一个属性,如下所示:

[AttributeUsage(AttributeTargets.Property)]
public class UppercaseAttribute : CustomModelBinderAttribute
{
    public override IModelBinder GetBinder()
    {
        return new UppercaseModelBinder();
    }

    private class UppercaseModelBinder : DefaultModelBinder
    {
        public override object BindModel(
            ControllerContext controllerContext,
            ModelBindingContext bindingContext)
        {
            var value = base.BindModel(controllerContext, bindingContext);
            var strValue = value as string;
            if (strValue == null)
                return value;
            return strValue.ToUpperInvariant();
        }
    }
}

我没有测试过这个。让我知道它是否有效。

答案 3 :(得分:0)

注意: 我正在添加这篇文章,因为在我发现我现在使用的方法之前,我读了这篇文章并尝试了上述所有方法。

在处理强制文本数据格式化为大写时,我通常使用两部分进程。 1.在视图和2.在控制器

  1. 在视图层,以便用户知道数据将以大写形式使用。这可以通过EditorFor HTML帮助程序中使用的htmlAttributes来实现。

    @HTML.EditorFor(model => model.Access_Code, new { htmlAttributes = new  Style= "text-transform:uppercase"}})
    
  2. 现在,这只会强制用户看到和输入的数据为大写,而不是发送到服务器的数据。要做到这一点,需要在控制器中的相关方法中使用一些代码。

    1. 我将ToUpper()方法添加到要传递回控制器的对象的target属性。这是一个假设的例子,显示了这一点。

      public ActionResult verify(int? id)
            {
              var userData = db.user.Where (i=> i.userID == id).Single();
      
              userData.Access_Code = userData.Access_Code.ToUpper();
      
         ...
       }