I am working in MVC4 and want to define a model using an Uppercase attribute. The idea would be that the presence of the Uppercase attribute would cause the mod
I have managed to get this working, to a point, so here's my solution for others to appraise.
Once point to note was that the full solution couldn't be achieved because I couldn't get the Modelmetadata inside the StringValidation.IsValid() attribute. The particular issue I had here was that I could get the Metadata, however I could not get the PropertyName from it, only the DisplayName. There were multiple options out there, but the fact that some of my properties have the same DisplayName means that I couldn't be sure that the ProprtyName was the one I was actually validating.
Here's the code for the 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;
}
}
I then created a new IModelBinder implementation:
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 myGlobal.asax file:
ModelBinders.Binders.Add(typeof(string), new StringBinder());
The code so far will cause any string input coming into MVC to be converted to Uppercase if it has StringValidationAttribute attached to it on the model, and where the uppercase indicator has been set.
Next, to achieve my desire of making the html forms be uppercase too, I implemented a new EditorTemplate named 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 the CSS as;
.Uppercase {
text-transform: uppercase;
}
Hope this post helps some others out there.