質問

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?

役に立ちましたか?

解決

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

他のヒント

On your model class decorate that property with [Required] attribute. I.e.:

[Required]
public string ShortName {get; set;}

A newer way to do this in .NET Core is with TagHelpers.

https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro

Building on these examples (MaxLength, Label), you can extend the existing TagHelper to suit your needs.

RequiredTagHelper.cs

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Linq;

namespace ProjectName.TagHelpers
{
    [HtmlTargetElement("input", Attributes = "asp-for")]
    public class RequiredTagHelper : TagHelper
    {
        public override int Order
        {
            get { return int.MaxValue; }
        }

        [HtmlAttributeName("asp-for")]
        public ModelExpression For { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            base.Process(context, output); 

            if (context.AllAttributes["required"] == null)
            {
                var isRequired = For.ModelExplorer.Metadata.ValidatorMetadata.Any(a => a is RequiredAttribute);
                if (isRequired)
                {
                    var requiredAttribute = new TagHelperAttribute("required");
                    output.Attributes.Add(requiredAttribute);
                }
            }
        }
    }
}

You'll then need to add it to be used in your views:

_ViewImports.cshtml

@using ProjectName
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper "*, ProjectName"

Given the following model:

Foo.cs

using System;
using System.ComponentModel.DataAnnotations;

namespace ProjectName.Models
{
    public class Foo
    {
        public int Id { get; set; }

        [Required]
        [Display(Name = "Full Name")]
        public string Name { get; set; }
    }
}

and view (snippet):

New.cshtml

<label asp-for="Name"></label>
<input asp-for="Name"/>

Will result in this HTML:

<label for="Name">Full Name</label>
<input required type="text" data-val="true" data-val-required="The Full Name field is required." id="Name" name="Name" value=""/>

I hope this is helpful to anyone with same question but using .NET Core.

I needed the "required" HTML5 atribute, so I did something like this:

<%: Html.TextBoxFor(model => model.Name, new { @required = true })%>

@Erik's answer didn't fly for me.

Following did:

 @Html.TextBoxFor(m => m.ShortName,  new { data_val_required = "You need me" })

plus doing this manually under field I had to add error message container

@Html.ValidationMessageFor(m => m.ShortName, null, new { @class = "field-validation-error", data_valmsg_for = "ShortName" })

Hope this saves you some time.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top