Asp.Net MVC में DataAnnotations StringLength से एक टेक्स्ट बॉक्स की अधिकतम गति


80

मैं MVC2 एप्लिकेशन पर काम कर रहा हूं और पाठ इनपुट की अधिकतम गति निर्धारित करना चाहता हूं।

मैंने पहले ही डेटा एनोटेशन का उपयोग करके मॉडल ऑब्जेक्ट पर स्ट्रिंग स्ट्रेंथ विशेषता को परिभाषित किया है और यह सही ढंग से दर्ज स्ट्रिंग्स की लंबाई को मान्य कर रहा है।

जब मॉडल में पहले से ही जानकारी हो, तो मैं अपने विचार में एक ही सेटिंग को अधिकतम लंबाई की विशेषता से मैन्युअल रूप से दोहराना नहीं चाहता। क्या इसे करने का कोई तरीका है?

नीचे कोड स्निपेट:

मॉडल से:

[Required, StringLength(50)]
public string Address1 { get; set; }

दृश्य से:

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

मैं क्या करने से बचना चाहता हूं:

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

मैं यह आउटपुट प्राप्त करना चाहता हूं:

<input type="text" name="Address1" maxlength="50" class="text long"/>

क्या इसे करने का कोई तरीका है?


मुझे खेद है, मुझे नहीं पता कि डेटा घोषणाएँ किसके लिए अच्छी हैं? मेरा मतलब है, अगर लंबाई मानदंड बदल जाए तो क्या होगा? क्या कुछ मेटाडेटा के आधार पर इसे गतिशील (रनटाइम पर) नहीं चलाया जा सकता है?
12

जवाबों:


51

मैं प्रतिबिंब का सहारा लिए बिना इसे प्राप्त करने के किसी भी तरीके से अवगत नहीं हूं। आप एक सहायक विधि लिख सकते हैं:

public static MvcHtmlString CustomTextBoxFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression, 
    object htmlAttributes
)
{
    var member = expression.Body as MemberExpression;
    var stringLength = member.Member
        .GetCustomAttributes(typeof(StringLengthAttribute), false)
        .FirstOrDefault() as StringLengthAttribute;

    var attributes = (IDictionary<string, object>)new RouteValueDictionary(htmlAttributes);
    if (stringLength != null)
    {
        attributes.Add("maxlength", stringLength.MaximumLength);
    }
    return htmlHelper.TextBoxFor(expression, attributes);
}

जो आप इस तरह उपयोग कर सकते हैं:

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

मुझे त्रुटि 1 'System.Web.Mvc.HtmlHelper <TModel> मिल रही है, जिसमें' TextBoxFor 'के लिए कोई परिभाषा नहीं है और कोई एक्सटेंशन विधि' TextBoxFor 'टाइप के पहले तर्क को स्वीकार नहीं कर रही है' System.Web.MtmlHelper <TModel > 'पाया जा सकता है (क्या आप इस दिशा में एक निर्देश या विधानसभा संदर्भ का उपयोग कर याद कर रहे हैं?) htmlHelper.TextBoxFor <TModel> (अभिव्यक्ति, गुण) लौटाएं;
सबबोर

2
हाँ, मुझे लगा कि पहले से ही :) मुझे एक और समस्या है, हालांकि, मेरे डेटा एनोटेशन को मॉडल के बजाय मेटाडेटा कक्षाओं पर परिभाषित किया गया है। प्रतिबिंब उन्हें नहीं उठा रहा है!
सब्बोर

जवाब के लिए धन्यवाद। मुझे उन विशेषताओं के साथ समस्या हो रही है जिनमें _ शामिल हैं, वे स्वचालित रूप से परिवर्तित नहीं होते हैं -। क्या आप मैन्युअल रूप से _ को बदलने और एक नया रूटवैल्यूडाउन भरने की तुलना में एक अलग तरीका जानते हैं।
LdN

यह जवाब उन मामलों के लिए काम नहीं करता है जहां मॉडल संपत्ति है। उदाहरण के लिए, एक स्ट्रिंग के लिए एक संपादक टेम्पलेट। नीचे डेव क्लेमर का जवाब सभी मामलों को संभालता है।
माइकल ब्रैंडन मॉरिस

59

यदि आप विनीत मान्यता का उपयोग कर रहे हैं, तो आप इस ग्राहक पक्ष को भी संभाल सकते हैं:

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

जब तक आपका दृष्टिकोण मुझे मान्यता प्रदान करता है - मैं वास्तव में इनपुट पर अधिकतम गति को डालने के बाद था क्योंकि यह उपयोगकर्ता को ब्राउज़र में अधिक वर्णों को डालने से रोक देगा और इस बात पर ध्यान दिए बिना काम करेगा कि क्या ब्राउज़र में जावास्क्रिप्ट चल रही थी।
परवेज चौधरी

5
ठीक यही करता है। यह इनपुट अधिकतम लंबाई विशेषता सेट करने के लिए डेटा अधिकतम लंबाई सत्यापन विशेषता का उपयोग करता है।
jrummell

5
मैं पहले प्रतिबिंब उत्तर से वास्तव में उत्साहित था, लेकिन यह बिना किसी जटिल सर्वर कोड के समान परिणाम प्राप्त करने के लिए लगता है। बहुत बढ़िया। आपको ज्यादा वोट मिलने चाहिए।
ब्रायन व्हाइट

1
+1 अजाक्स रूपों के लिए महान विचार। मैं ब्रायन व्हाइट से सहमत हूं कि यह उत्तर अधिक वोटों का हकदार है।
इलिसा जूल

1
मैं जावास्क्रिप्ट के बिना ओपी सत्यापन की जरूरत के बारे में हिस्सा याद किया। लेकिन मुझे खुशी है कि इससे दूसरों को एक जावास्क्रिप्ट समाधान की तलाश में मदद मिली है।
jrummell

20

मैं इसे प्राप्त करने के लिए CustomModelMetaDataProvider का उपयोग करता हूं

चरण 1. नया CustomModelMetadataProvider वर्ग जोड़ें

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{   
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes,
        Type containerType,
        Func<object> modelAccessor,
        Type modelType,
        string propertyName)
    {
        ModelMetadata metadata = base.CreateMetadata(attributes,
            containerType,
            modelAccessor,
            modelType,
            propertyName);

        //Add MaximumLength to metadata.AdditionalValues collection
        var stringLengthAttribute = attributes.OfType<StringLengthAttribute>().FirstOrDefault();
        if (stringLengthAttribute != null)
            metadata.AdditionalValues.Add("MaxLength", stringLengthAttribute.MaximumLength);

        return metadata;
    }
}

चरण 2. Global.asax में CustomModelMetadataProvider पंजीकृत करें

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

चरण 3. दृश्य / साझा / EditorTemplates में एक आंशिक दृश्य जोड़ें जिसे String.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  })%>
<% } %>

किया हुआ...

संपादित करें। यदि आप पाठ बॉक्स में अधिक सामग्री जोड़ना चाहते हैं, तो चरण 3 बदसूरत होना शुरू हो सकता है। यदि यह आपका मामला है तो आप निम्नलिखित कार्य कर सकते हैं:

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

8

यदि आप चाहते हैं कि यह मेटाडेटा वर्ग के साथ काम करे तो आपको निम्नलिखित कोड का उपयोग करने की आवश्यकता है। मुझे पता है कि यह बहुत सुंदर नहीं है, लेकिन यह काम पूरा कर देता है और आपको इकाई वर्ग और दृश्य दोनों में अपनी अधिकतम गति को लिखने से रोकता है:

public static MvcHtmlString TextBoxFor2<TModel, TProperty>
(
  this HtmlHelper<TModel> htmlHelper,
  Expression<Func<TModel, TProperty>> expression,
  object htmlAttributes = null
)
{
  var member = expression.Body as MemberExpression;

  MetadataTypeAttribute metadataTypeAttr = member.Member.ReflectedType
    .GetCustomAttributes(typeof(MetadataTypeAttribute), false)
    .FirstOrDefault() as MetadataTypeAttribute;

  IDictionary<string, object> htmlAttr = null;

  if(metadataTypeAttr != null)
  {
    var stringLength = metadataTypeAttr.MetadataClassType
      .GetProperty(member.Member.Name)
      .GetCustomAttributes(typeof(StringLengthAttribute), false)
      .FirstOrDefault() as StringLengthAttribute;

    if (stringLength != null)
    {
      htmlAttr = new RouteValueDictionary(htmlAttributes);
      htmlAttr.Add("maxlength", stringLength.MaximumLength);
    }                                    
  }

  return htmlHelper.TextBoxFor(expression, htmlAttr);
}

उदाहरण वर्ग :

[MetadataType(typeof(Person.Metadata))]
public partial class Person
{
  public sealed class Metadata
  {

    [DisplayName("First Name")]
    [StringLength(30, ErrorMessage = "Field [First Name] cannot exceed 30 characters")]
    [Required(ErrorMessage = "Field [First Name] is required")]
    public object FirstName { get; set; }

    /* ... */
  }
}

3

जबकि मैं व्यक्तिगत रूप से jrummel के jquery फिक्स को प्यार कर रहा हूं, यहां एक एकल-स्रोत को अपने सत्य में बनाए रखने के लिए एक और दृष्टिकोण है ...

नहीं सुंदर, लेकिन .. मेरे लिए ठीक काम किया है ...

प्रॉपर्टी डेकोरेशन का उपयोग करने के बजाय, मैं अपने मॉडल लाइब्रेरी / dll में कुछ अच्छी तरह से नामित सार्वजनिक स्थिरांक को परिभाषित करता हूं, और फिर उन्हें मेरे विचार में HtmlAttributes, उदा।

Public Class MyModel

    Public Const MAX_ZIPCODE_LENGTH As Integer = 5

    Public Property Address1 As String

    Public Property Address2 As String

    <MaxLength(MAX_ZIPCODE_LENGTH)>
    Public Property ZipCode As String

    Public Property FavoriteColor As System.Drawing.Color

End Class

फिर, रेज़र व्यू फ़ाइल में, EditorFor में ... अधिभार में एक HtmlAttirubte ऑब्जेक्ट का उपयोग करें, वांछित अधिकतम-लंबाई की संपत्ति की आपूर्ति करें और स्थिर का संदर्भ दें .. आपको पूरी तरह से योग्य नाम स्थान पथ के माध्यम से निरंतर आपूर्ति करनी होगी। .. MyCompany.MyModel.MAX_ZIPCODE_LENGTH .. क्योंकि यह मॉडल से सही लटका नहीं होगा, लेकिन, यह काम करता है।


2

मैंने डारिन के प्रतिबिंब आधारित दृष्टिकोण को विशेष रूप से उपयोगी पाया। मैंने पाया कि ContainerTypeसंपत्ति की जानकारी प्राप्त करने के लिए आधार के रूप में मेटाडेटा का उपयोग करना थोड़ा अधिक विश्वसनीय था , क्योंकि इस विधि को mvc संपादक / डिस्प्ले टेम्प्लेट के भीतर बुलाया जा सकता है (जहां TModelएक सरल प्रकार जैसे समाप्त होता है string)।

public static MvcHtmlString CustomTextBoxFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression, 
    object htmlAttributes
)
{
    var metadata = ModelMetadata.FromLambdaExpression( expression, new ViewDataDictionary<TModel>( htmlHelper.ViewDataContainer.ViewData ) );
    var stringLength = metadata.ContainerType.GetProperty(metadata.PropertyName)
        .GetCustomAttributes(typeof(StringLengthAttribute), false)
        .FirstOrDefault() as StringLengthAttribute;

    var attributes = (IDictionary<string, object>)new RouteValueDictionary(htmlAttributes);
    if (stringLength != null)
    {
        attributes.Add("maxlength", stringLength.MaximumLength);
    }
    return htmlHelper.TextBoxFor(expression, attributes);
}

1

यहाँ कुछ स्थिर विधियाँ हैं जिनका उपयोग आप StringLength, या किसी अन्य विशेषता को प्राप्त करने के लिए कर सकते हैं।

using System;
using System.Linq;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using System.Linq.Expressions;

public static class AttributeHelpers {

public static Int32 GetStringLength<T>(Expression<Func<T,string>> propertyExpression) {
    return GetPropertyAttributeValue<T,string,StringLengthAttribute,Int32>(propertyExpression,attr => attr.Length);
}

//Optional Extension method
public static Int32 GetStringLength<T>(this T instance,Expression<Func<T,string>> propertyExpression) {
    return GetStringLength<T>(propertyExpression);
}


//Required generic method to get any property attribute from any class
public static TValue GetPropertyAttributeValue<T, TOut, TAttribute, TValue>(Expression<Func<T,TOut>> propertyExpression,Func<TAttribute,TValue> valueSelector) where TAttribute : Attribute {
    var expression = (MemberExpression)propertyExpression.Body;
    var propertyInfo = (PropertyInfo)expression.Member;
    var attr = propertyInfo.GetCustomAttributes(typeof(TAttribute),true).FirstOrDefault() as TAttribute;

    if (attr==null) {
        throw new MissingMemberException(typeof(T).Name+"."+propertyInfo.Name,typeof(TAttribute).Name);
    }

    return valueSelector(attr);
}

}

स्थैतिक विधि का उपयोग ...

var length = AttributeHelpers.GetStringLength<User>(x => x.Address1);

या एक उदाहरण पर वैकल्पिक विस्तार विधि का उपयोग कर ...

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

या किसी अन्य विशेषता के लिए पूर्ण स्थैतिक विधि का उपयोग कर ...

var length = AttributeHelpers.GetPropertyAttributeValue<User,string,StringLengthAttribute,Int32>(prop => prop.Address1,attr => attr.MaximumLength);

यहाँ उत्तर से प्रेरित ... https://stackoverflow.com/a/32501356/324479

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.