Atsortingbut maxlength d’une zone de texte à partir de la propriété SsortingngAnnotations SsortingngLength d’Asp.Net MVC

Je travaille sur une application MVC2 et je souhaite définir les atsortingbuts maxlength des entrées de texte.

J’ai déjà défini l’atsortingbut ssortingnglength sur l’object Model en utilisant les annotations de données et il valide la longueur des chaînes entrées correctement.

Je ne souhaite pas répéter le même paramètre dans mes vues en définissant manuellement l’atsortingbut Longueur maximale lorsque le modèle contient déjà les informations. Est-ce qu’il y a un moyen de faire ça?

Extraits de code ci-dessous:

Du modèle:

[Required, SsortingngLength(50)] public ssortingng Address1 { get; set; } 

De la vue:

  model.Address1) %>  model.Address1, new { @class = "text long" })%>  model.Address1) %> 

Ce que je veux éviter, c’est:

  model.Address1, new { @class = "text long", maxlength="50" })%> 

Je veux obtenir cette sortie:

  

Est-ce qu’il y a un moyen de faire ça?

Je ne suis au courant d’aucun moyen d’y parvenir sans avoir recours à la reflection. Vous pourriez écrire une méthode d’assistance:

 public static MvcHtmlSsortingng CustomTextBoxFor( this HtmlHelper htmlHelper, Expression> expression, object htmlAtsortingbutes ) { var member = expression.Body as MemberExpression; var ssortingngLength = member.Member .GetCustomAtsortingbutes(typeof(SsortingngLengthAtsortingbute), false) .FirstOrDefault() as SsortingngLengthAtsortingbute; var atsortingbutes = (IDictionary)new RouteValueDictionary(htmlAtsortingbutes); if (ssortingngLength != null) { atsortingbutes.Add("maxlength", ssortingngLength.MaximumLength); } return htmlHelper.TextBoxFor(expression, atsortingbutes); } 

que vous pourriez utiliser comme ceci:

 <%= Html.CustomTextBoxFor(model => model.Address1, new { @class = "text long" })%> 

Si vous utilisez une validation discrète, vous pouvez également gérer ce côté client:

 $(document).ready(function () { $("input[data-val-length-max]").each(function () { var $this = $(this); var data = $this.data(); $this.attr("maxlength", data.valLengthMax); }); }); 

J’utilise le CustomModelMetaDataProvider pour y parvenir

Étape 1. Ajouter une nouvelle classe CustomModelMetadataProvider

 public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider { protected override ModelMetadata CreateMetadata( IEnumerable atsortingbutes, Type containerType, Func modelAccessor, Type modelType, ssortingng propertyName) { ModelMetadata metadata = base.CreateMetadata(atsortingbutes, containerType, modelAccessor, modelType, propertyName); //Add MaximumLength to metadata.AdditionalValues collection var ssortingngLengthAtsortingbute = atsortingbutes.OfType().FirstOrDefault(); if (ssortingngLengthAtsortingbute != null) metadata.AdditionalValues.Add("MaxLength", ssortingngLengthAtsortingbute.MaximumLength); return metadata; } } 

Étape 2. Dans Global.asax Enregistrez le CustomModelMetadataProvider

 protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); ModelMetadataProviders.Current = new CustomModelMetadataProvider(); } 

Étape 3. Dans Views / Shared / EditorTemplates Ajoutez une vue partielle appelée Ssortingng.ascx

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> <%if (!ViewData.ModelMetadata.AdditionalValues.ContainsKey("MaxLength")) { %> <%: Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line" }) %> <% } else { int maxLength = (int)ViewData.ModelMetadata.AdditionalValues["MaxLength"]; %> <%: Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", MaxLength = maxLength })%> <% } %> 

Terminé…

Modifier. L’étape 3 peut commencer à devenir laide si vous voulez append plus de choses à la zone de texte. Si tel est votre cas, vous pouvez effectuer les opérations suivantes:

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> <% IDictionary Atsortingbutes = new Dictionary(); if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("MaxLength")) { Atsortingbutes.Add("MaxLength", (int)ViewData.ModelMetadata.AdditionalValues["MaxLength"]); } if (ViewData.ContainsKey("style")) { Atsortingbutes.Add("style", (ssortingng)ViewData["style"]); } if (ViewData.ContainsKey("title")) { Atsortingbutes.Add("title", (ssortingng)ViewData["title"]); } %> <%: Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, Attributes)%> 

Si vous souhaitez que cela fonctionne avec une classe de métadonnées, vous devez utiliser le code suivant. Je sais que ce n’est pas joli, mais il fait le travail et vous empêche d’avoir à écrire vos propriétés maxlength à la fois dans la classe Entity et dans la vue:

 public static MvcHtmlSsortingng TextBoxFor2 ( this HtmlHelper htmlHelper, Expression> expression, object htmlAtsortingbutes = null ) { var member = expression.Body as MemberExpression; MetadataTypeAtsortingbute metadataTypeAttr = member.Member.ReflectedType .GetCustomAtsortingbutes(typeof(MetadataTypeAtsortingbute), false) .FirstOrDefault() as MetadataTypeAtsortingbute; IDictionary htmlAttr = null; if(metadataTypeAttr != null) { var ssortingngLength = metadataTypeAttr.MetadataClassType .GetProperty(member.Member.Name) .GetCustomAtsortingbutes(typeof(SsortingngLengthAtsortingbute), false) .FirstOrDefault() as SsortingngLengthAtsortingbute; if (ssortingngLength != null) { htmlAttr = new RouteValueDictionary(htmlAtsortingbutes); htmlAttr.Add("maxlength", ssortingngLength.MaximumLength); } } return htmlHelper.TextBoxFor(expression, htmlAttr); } 

Exemple de classe :

 [MetadataType(typeof(Person.Metadata))] public partial class Person { public sealed class Metadata { [DisplayName("First Name")] [SsortingngLength(30, ErrorMessage = "Field [First Name] cannot exceed 30 characters")] [Required(ErrorMessage = "Field [First Name] is required")] public object FirstName { get; set; } /* ... */ } } 

Alors que j’aime personnellement le jquery de jrummel, voici une autre approche pour garder une source unique de vérité dans votre modèle …

Pas joli, mais ça a bien fonctionné pour moi …

Au lieu d’utiliser des décorations de propriétés, je définis simplement des constantes publiques bien nommées dans ma bibliothèque de modèles / dll, puis je les référence dans ma vue via HtmlAtsortingbutes, par exemple

 Public Class MyModel Public Const MAX_ZIPCODE_LENGTH As Integer = 5 Public Property Address1 As Ssortingng Public Property Address2 As Ssortingng  Public Property ZipCode As Ssortingng Public Property FavoriteColor As System.Drawing.Color End Class 

Ensuite, dans le fichier de vue du razor, dans EditorFor … utilisez un object HtmlAttirubte dans la surcharge, indiquez la propriété de longueur maximale souhaitée et mentionnez la constante .. vous devrez fournir la constante via un chemin d’access de l’espace de noms entièrement qualifié. .. MyCompany.MyModel.MAX_ZIPCODE_LENGTH .. comme il ne sera pas suspendu directement sur le modèle, mais cela fonctionne.

J’ai trouvé que l’approche basée sur la reflection de Darin était particulièrement utile. J’ai trouvé qu’il était un peu plus fiable d’utiliser metadata ContainerType comme base pour obtenir les informations de propriété, car cette méthode peut être appelée dans l’éditeur / mvc editor templates (où TModel finit par être un type simple tel que ssortingng ).

 public static MvcHtmlSsortingng CustomTextBoxFor( this HtmlHelper htmlHelper, Expression> expression, object htmlAtsortingbutes ) { var metadata = ModelMetadata.FromLambdaExpression( expression, new ViewDataDictionary( htmlHelper.ViewDataContainer.ViewData ) ); var ssortingngLength = metadata.ContainerType.GetProperty(metadata.PropertyName) .GetCustomAtsortingbutes(typeof(SsortingngLengthAtsortingbute), false) .FirstOrDefault() as SsortingngLengthAtsortingbute; var atsortingbutes = (IDictionary)new RouteValueDictionary(htmlAtsortingbutes); if (ssortingngLength != null) { atsortingbutes.Add("maxlength", ssortingngLength.MaximumLength); } return htmlHelper.TextBoxFor(expression, atsortingbutes); } 

Voici quelques méthodes statiques que vous pouvez utiliser pour obtenir SsortingngLength, ou tout autre atsortingbut.

 using System; using System.Linq; using System.Reflection; using System.ComponentModel.DataAnnotations; using System.Linq.Expressions; public static class AtsortingbuteHelpers { public static Int32 GetSsortingngLength(Expression> propertyExpression) { return GetPropertyAtsortingbuteValue(propertyExpression,attr => attr.Length); } //Optional Extension method public static Int32 GetSsortingngLength(this T instance,Expression> propertyExpression) { return GetSsortingngLength(propertyExpression); } //Required generic method to get any property atsortingbute from any class public static TValue GetPropertyAtsortingbuteValue(Expression> propertyExpression,Func valueSelector) where TAtsortingbute : Atsortingbute { var expression = (MemberExpression)propertyExpression.Body; var propertyInfo = (PropertyInfo)expression.Member; var attr = propertyInfo.GetCustomAtsortingbutes(typeof(TAtsortingbute),true).FirstOrDefault() as TAtsortingbute; if (attr==null) { throw new MissingMemberException(typeof(T).Name+"."+propertyInfo.Name,typeof(TAtsortingbute).Name); } return valueSelector(attr); } } 

En utilisant la méthode statique …

 var length = AtsortingbuteHelpers.GetSsortingngLength(x => x.Address1); 

Ou en utilisant la méthode d’extension facultative sur une instance …

 var player = new User(); var length = player.GetSsortingngLength(x => x.Address1); 

Ou en utilisant la méthode statique complète pour tout autre atsortingbut …

 var length = AtsortingbuteHelpers.GetPropertyAtsortingbuteValue(prop => prop.Address1,attr => attr.MaximumLength); 

Inspiré par la réponse ici … https://stackoverflow.com/a/32501356/324479