A top-level attribute that converts input to uppercase

I work in MVC4 and want to define a model using the Uppercase attribute. The idea would be that having the Uppercase attribute convert the model value to uppercase when it reaches the server.

Currently, I have the following code in the model:

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

But I would really like to:

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

I think I might need to create an Uppercase attribute as a ValidationAttribute to make sure it is running when the model hits the server. But this seems a bit wrong, as I really don't check the data. Is there a better way?

Also, is there a way to ensure the order in which attributes are called? I really want to convert the data to uppercase before the custom StringValidation attribute starts, as this will check the case of text in the regex pattern.

To add a bit of background to this, I want to reduce the need to add code for uppercase data. Nirvana will be the only attribute that updates data on the way to the server, either at the model binding stage or at the verification stage. This attribute can then be referenced in the StringValidation attribute to change the RegEx value used in its checks. I can also find this attribute in a special TextBoxFor helper method, so that I can add text-transform: uppercase so that it looks right on the client side.

Does anyone have any ideas?

+6
source share
4 answers

I managed to get this job, and this is my decision for others to appreciate.

As soon as we note that a complete solution cannot be reached because I could not get the Modelmetadata inside the StringValidation.IsValid() attribute. The special question I had here was that I could get metadata, however I could not get PropertyName from it, only DisplayName . There were several options, but the fact that some of my properties have the same DisplayName means that I could not be sure that ProprtyName was the one I was actually checking.

Here is the code for 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; } } 

Then I created a new implementation of 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; } } 

And registered that in my Global.asax file:

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

The code still leads to the fact that any line input coming into MVC will be converted to upper case if StringValidationAttribute attached to it and where the upper indicator is set.

Further, in order to achieve my desire to make html forms also in capital letters, I implemented a new EditorTemplate called string.cshtml . In this view, I added:

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

With CSS as;

 .Uppercase { text-transform: uppercase; } 

Hope this post helps some others out there.

+5
source

You are correct, ValidationAttribute not suitable. It seems like doing this at the β€œLink to Model” stage would be a better idea. See this article for a detailed explanation of how to configure this behavior.

Based on the information provided there, I believe that you should be able to create an attribute based on CustomModelBinderAttribute as follows:

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

I have not tested this. Let me know if this works or not.

0
source

For Web API purposes, it is better to convert the incoming json to uppercase or lowercase.

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

OR globally;

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

Note: I am adding to this post because, until I discovered the approach that I am currently using, I read this and tried all of this unsuccessfully.

I usually use a two-part process when working with text formatting in uppercase. 1. by sight and 2. on the controller

  • At the presentation level, so that the user knows that the data will be used in capital form. This can be omitted through the htmlAttributes used in the HTML editorForFor helper.

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

Now it only forces the data to be viewed and entered by the user in uppercase, and not on the data sent to the server. This requires some code in a related method in the controller.

  1. I add the ToUpper () method to the target attribute of the object, which is passed back to the controller. Here is a hypothetical example showing this.

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

Source: https://habr.com/ru/post/949661/


All Articles