开发者

ASP.NET MVC 3 - Data Annoation and Max Length/Size for Textbox Rendering

开发者 https://www.devze.com 2023-04-01 01:11 出处:网络
I know on the Razor View file, we can do something like this @Html.TextBox(\"username\", null, new { maxlength = 20, autocomplete = \"off\" })

I know on the Razor View file, we can do something like this @Html.TextBox("username", null, new { maxlength = 20, autocomplete = "off" })

However, I am hoping to create a model for the MVC that can be used to create a form with explicitly defined the size and max length of the textboxes. I try [StringLength(n)] on top of the properties of the model, but that seems to only do the validation ratherh set the 开发者_Go百科size of the textbox.

Is there anyway that we can define the length of the text field as a data annotation on top of a property of a model?

So ultimately, we could just create the whole form by using razor to map to a model rather than explicitly pick up the model properties one by one in order to set the textbox size.


Here is a outline of a custom helper that uses StringLengthAttribute.

public class MyModel
{
    [StringLength(50)]
    public string Name{get; set;}
}

public MvcHtmlString MyTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, 
      Expression<Func<TModel, TProperty>> expression)
{

    var attributes = new Dictionary<string, Object>();
    var memberAccessExpression = (MemberExpression)expression.Body;
    var stringLengthAttribs = memberAccessExpression.Member.GetCustomAttributes(
        typeof(System.ComponentModel.DataAnnotations.StringLengthAttribute), true);

    if (stringLengthAttribs.Length > 0)
    {
        var length = ((StringLengthAttribute)stringLengthAttribs[0]).MaximumLength;

        if (length > 0) 
        {
             attributes.Add("size", length);
             attributes.Add("maxlength", length);
        }
    }

    return helper.TextBoxFor(expression, attributes);
}


Does this not work?

public class ViewModel
{
    [StringLength(20)]
    public string UserName {get;set;}
}

In the View:

@Html.TextBoxFor(x => x.UserName, new {autocomplete = "off"})

or:

@Html.EditorFor(x => x.UserName)


I find that I prefer my views to just Call Html.EditorFor(...). This means that the Editor and Display templates decide the fate of controls in my view, such that my view code gets cleaned up a lot - it just has html and generic requests for editors.

The following link gives a working sample of getting this working in an Editor Template https://jefferytay.wordpress.com/2011/12/20/asp-net-mvc-string-editor-template-which-handles-the-stringlength-attribute/

I'm using similar in my String.cshtml Editor Template (goes in Shared/EditorTemplates ).

@model object
@using System.ComponentModel.DataAnnotations
@{
    ModelMetadata meta = ViewData.ModelMetadata;
    Type tModel = meta.ContainerType.GetProperty(meta.PropertyName).PropertyType;
}
@if(typeof(string).IsAssignableFrom(tModel)) {

    var htmlOptions = new System.Collections.Generic.Dictionary<string, object>();

    var stringLengthAttribute = (StringLengthAttributeAdapter)ViewData.ModelMetadata.GetValidators(this.ViewContext.Controller.ControllerContext).Where(v => v is StringLengthAttributeAdapter).FirstOrDefault();
    if (stringLengthAttribute != null && stringLengthAttribute.GetClientValidationRules().First().ValidationParameters["max"] != null)
    {
        int maxLength = (int)stringLengthAttribute.GetClientValidationRules().First().ValidationParameters["max"];

        htmlOptions.Add("maxlength", maxLength);

        if (maxLength < 20)
        {
            htmlOptions.Add("size", maxLength);
        }
    }

    htmlOptions.Add("class", "regular-field");

    <text>
         @Html.TextBoxFor(m => m, htmlOptions)
    </text>
}
else if(typeof(Enum).IsAssignableFrom(tModel)) {
    //Show a Drop down for an enum using:
    //Enum.GetValues(tModel)
    //This is beyond this article
}
//Do other things for other types...

Then my model is annotated such as:

[Display(Name = "Some Field", Description = "Description of Some Field")]
[StringLength(maximumLength: 40, ErrorMessage = "{0} max length {1}.")]
public string someField{ get; set; }

And my View simply calls:

<div class="editor-label">
    @Html.LabelWithTooltipFor(model => model.something.someField)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.something.someField)
    @Html.ValidationMessageFor(model => model.something.someField)
</div>

You might also notice that my String.cshtml Editor Template also auto-magically handles Enum's, but that is starting to digress from the current topic, so I nixed that code, I'll just say here that the String Editor Template can pull extra weight, and likely google has someting on that https://www.google.com/search?q=string+editor+template+enum

Label With Tooltip For is a custom HTML helper that just drops the description into the label title, for more information on mouse over for every label.

I'd recommend this approach if you want to do this in an Editor Template.

0

精彩评论

暂无评论...
验证码 换一张
取 消