我在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
,使其在客户端看起来正确。
有没有人有任何想法?
答案 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.在控制器
在视图层,以便用户知道数据将以大写形式使用。这可以通过EditorFor HTML帮助程序中使用的htmlAttributes来实现。
@HTML.EditorFor(model => model.Access_Code, new { htmlAttributes = new Style= "text-transform:uppercase"}})
现在,这只会强制用户看到和输入的数据为大写,而不是发送到服务器的数据。要做到这一点,需要在控制器中的相关方法中使用一些代码。
我将ToUpper()方法添加到要传递回控制器的对象的target属性。这是一个假设的例子,显示了这一点。
public ActionResult verify(int? id)
{
var userData = db.user.Where (i=> i.userID == id).Single();
userData.Access_Code = userData.Access_Code.ToUpper();
...
}