Search code examples
asp.net-mvcrazordata-annotationshtml-helper

How to add "required" attribute to mvc razor viewmodel text input editor


I have the following MVC 5 Razor HTML helper:

@Html.TextBoxFor(m => m.ShortName, 
  new { @class = "form-control", @placeholder = "short name"})

I need this field to be required (i.e. have a red outline when user navigates out without putting a value inn). In a WebForms HTML 5 I could just say <input type="text" required /> to have this effect. What is the proper syntax to accomplish this in a Razor syntax?


Solution

  • You can use the required html attribute if you want:

    @Html.TextBoxFor(m => m.ShortName, 
    new { @class = "form-control", placeholder = "short name", required="required"})
    

    or you can use the RequiredAttribute class in .Net. With jQuery the RequiredAttribute can Validate on the front end and server side. If you want to go the MVC route, I'd suggest reading Data annotations MVC3 Required attribute.

    OR

    You can get really advanced:

    @{
      // if you aren't using UnobtrusiveValidation, don't pass anything to this constructor
      var attributes = new Dictionary<string, object>(
        Html.GetUnobtrusiveValidationAttributes(ViewData.TemplateInfo.HtmlFieldPrefix));
    
     attributes.Add("class", "form-control");
     attributes.Add("placeholder", "short name");
    
      if (ViewData.ModelMetadata.ContainerType
          .GetProperty(ViewData.ModelMetadata.PropertyName)
          .GetCustomAttributes(typeof(RequiredAttribute), true)
          .Select(a => a as RequiredAttribute)
          .Any(a => a != null))
      {
       attributes.Add("required", "required");
      }
    
      @Html.TextBoxFor(m => m.ShortName, attributes)
    
    }
    

    or if you need it for multiple editor templates:

    public static class ViewPageExtensions
    {
      public static IDictionary<string, object> GetAttributes(this WebViewPage instance)
      {
        // if you aren't using UnobtrusiveValidation, don't pass anything to this constructor
        var attributes = new Dictionary<string, object>(
          instance.Html.GetUnobtrusiveValidationAttributes(
             instance.ViewData.TemplateInfo.HtmlFieldPrefix));
    
        if (ViewData.ModelMetadata.ContainerType
          .GetProperty(ViewData.ModelMetadata.PropertyName)
          .GetCustomAttributes(typeof(RequiredAttribute), true)
          .Select(a => a as RequiredAttribute)
          .Any(a => a != null))
        {
          attributes.Add("required", "required");
        }
      }
    }
    

    then in your templates:

    @{
      // if you aren't using UnobtrusiveValidation, don't pass anything to this constructor
      var attributes = this.GetAttributes();
    
      attributes.Add("class", "form-control");
      attributes.Add("placeholder", "short name");
    
      @Html.TextBoxFor(m => m.ShortName, attributes)
    
    }
    

    Update 1 (for Tomas who is unfamilar with ViewData).

    What's the difference between ViewData and ViewBag?

    Excerpt:

    So basically it (ViewBag) replaces magic strings:

    ViewData["Foo"]
    

    with magic properties:

    ViewBag.Foo