7

我在 MVC4 中工作并想使用Uppercase属性定义模型。想法是,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; }

我认为我可能需要创建 Uppercase 属性作为 aValidationAttribute以确保它在模型命中服务器时被触发。但这似乎有点错误,因为我并没有真正验证数据。有没有更好的办法?

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

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

有没有人有任何想法?

4

4 回答 4

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

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

于 2013-07-24T16:48:04.253 回答
3

对于 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;
    }
于 2017-05-24T14:05:32.833 回答
0

你是对的,ValidationAttribute不是合适的人选。在模型绑定阶段这样做似乎是一个更好的主意。有关如何自定义此行为的详细说明,请参阅本文。

根据那里提供的信息,我相信您应该能够基于以下内容创建属性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();
        }
    }
}

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

于 2013-07-19T16:40:48.477 回答
0

注意: 我在这篇文章中添加了内容,因为在我发现我现在使用的方法之前,我阅读了这篇文章并尝试了上述所有方法,但均未成功。

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

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

    @HTML.EditorFor(model => model.Access_Code, new { htmlAttributes = new  Style= "text-transform:uppercase"}})
    

现在这只强制用户看到和输入的数据为大写,而不是发送到服务器的数据。为此,需要在控制器的关联方法中编写一些代码。

  1. 我将 ToUpper() 方法添加到传递回控制器的对象的目标属性中。这是显示这一点的假设示例。

    public ActionResult verify(int? id)
          {
            var userData = db.user.Where (i=> i.userID == id).Single();
    
            userData.Access_Code = userData.Access_Code.ToUpper();
    
       ...
     }
    
于 2015-11-13T20:12:02.843 回答