-1

I was following this YouTube tutorial for MVC and I had some doubts regarding the EditorFor and LabelFor HTMLHelpers and looked it up online. Found this blog which explains in detail. However, in the blog, the mentions that we need to have the [datatype].cshtml file in our Views\Shared folder for us to be able to apply the EditorFor/LabelFor methods to the properties of datatype [datatype]. But in my project, I don't see any String.cshtml file anywhere in the solution. So how come I am able to use the EditorFor method for AccountNumber property which is of datatype String. Sample code below

Shouldn't I be having the String.cshtml file in Views\Shared folder to use these EditorFor methods?

 <div class="form-group">
        @Html.LabelFor(model => model.AccountNumber, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.AccountNumber, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.AccountNumber, "", new { @class = "text-danger" })
        </div>
    </div>
karun_r
  • 183
  • 1
  • 2
  • 14
  • Because the source code include default [DisplayTemplates](https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/Html/DefaultDisplayTemplates.cs) and [EditorTemplates](https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/Html/DefaultEditorTemplates.cs) for use by the `DisplayFor()` and `EditorFor()` methods –  Oct 12 '16 at 05:08

1 Answers1

0

As Stephen Muecke mentioned in the comments, there are default templates in the System.Web.Mvc.Html namespace. I think the comment really says it all, but I'll try to clarify what's going on behind the scenes. If you check the source code for EditorFor you will eventually end up at the internal static TemplateHelpers, which contain dictionaries for some default types, which in turn use DefaultEditorTemplates. These are used until you actually override them yourself by placing a view inside the folders Shared/EditorTemplates or Shared/DisplayTemplates. So, even if Boolean is in the dictionary of the default templates, you may override it by placing Boolean.cshtml in the on of the folders.

From TemplateHelpers:

private static readonly Dictionary<string, Func<HtmlHelper, string>> _defaultEditorActions = new Dictionary<string, Func<HtmlHelper, string>>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase) {
  { "HiddenInput", new Func<HtmlHelper, string>(DefaultEditorTemplates.HiddenInputTemplate) },
  { "MultilineText", new Func<HtmlHelper, string>(DefaultEditorTemplates.MultilineTextTemplate) },
  { "Password", new Func<HtmlHelper, string>(DefaultEditorTemplates.PasswordTemplate) },
  { "Text", new Func<HtmlHelper, string>(DefaultEditorTemplates.StringTemplate) },
  { "Collection", new Func<HtmlHelper, string>(DefaultEditorTemplates.CollectionTemplate) },
  { "PhoneNumber", new Func<HtmlHelper, string>(DefaultEditorTemplates.PhoneNumberInputTemplate) },
  { "Url", new Func<HtmlHelper, string>(DefaultEditorTemplates.UrlInputTemplate) },
  { "EmailAddress", new Func<HtmlHelper, string>(DefaultEditorTemplates.EmailAddressInputTemplate) },
  { "DateTime", new Func<HtmlHelper, string>(DefaultEditorTemplates.DateTimeInputTemplate) },
  { "DateTime-local", new Func<HtmlHelper, string>(DefaultEditorTemplates.DateTimeLocalInputTemplate) },
  { "Date", new Func<HtmlHelper, string>(DefaultEditorTemplates.DateInputTemplate) },
  { "Time", new Func<HtmlHelper, string>(DefaultEditorTemplates.TimeInputTemplate) },
  { typeof (Color).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.ColorInputTemplate) },
  { typeof (byte).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.NumberInputTemplate) },
  { typeof (sbyte).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.NumberInputTemplate) },
  { typeof (int).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.NumberInputTemplate) },
  { typeof (uint).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.NumberInputTemplate) },
  { typeof (long).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.NumberInputTemplate) },
  { typeof (ulong).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.NumberInputTemplate) },
  { typeof (bool).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.BooleanTemplate) },
  { typeof (Decimal).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.DecimalTemplate) },
  { typeof (string).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.StringTemplate) },
  { typeof (object).Name, new Func<HtmlHelper, string>(DefaultEditorTemplates.ObjectTemplate) }
};

From DefaultEditorTemplates for creating a Boolean:

internal static string BooleanTemplate(HtmlHelper html)
{
  bool? nullable1 = new bool?();
  if (html.ViewContext.ViewData.Model != null)
    nullable1 = new bool?(Convert.ToBoolean(html.ViewContext.ViewData.Model, (IFormatProvider) CultureInfo.InvariantCulture));
  if (html.ViewContext.ViewData.ModelMetadata.IsNullableValueType)
    return DefaultEditorTemplates.BooleanTemplateDropDownList(html, nullable1);
  HtmlHelper html1 = html;
  bool? nullable2 = nullable1;
  int num = nullable2.HasValue ? (nullable2.GetValueOrDefault() ? 1 : 0) : 0;
  return DefaultEditorTemplates.BooleanTemplateCheckbox(html1, num != 0);
}

private static string BooleanTemplateCheckbox(HtmlHelper html, bool value)
{
  return InputExtensions.CheckBox(html, string.Empty, value, DefaultEditorTemplates.CreateHtmlAttributes(html, "check-box", (string) null)).ToHtmlString();
}

private static string BooleanTemplateDropDownList(HtmlHelper html, bool? value)
{
  return SelectExtensions.DropDownList(html, string.Empty, (IEnumerable<SelectListItem>) DefaultEditorTemplates.TriStateValues(value), DefaultEditorTemplates.CreateHtmlAttributes(html, "list-box tri-state", (string) null)).ToHtmlString();
}

Here's the source code from Core:

https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs

Community
  • 1
  • 1
smoksnes
  • 10,509
  • 4
  • 49
  • 74
  • Let's say I had to use a different behavior for a String field in one form and I choose to override the template for datatype String i.e. String.cshtml. So all the other places where I have string property in view files would also be affected? Looks like I am missing something really simple as that will not be the case. How do I cater to a special case scenario where I just have to have an exception in displaying a commonly used datatype ? – karun_r Oct 12 '16 at 05:33
  • @karun10 - That's a another question, but yes it will be used everywhere. But there are ways around it. First, you can pass parameters into it as such - [EditorFor() and html properties](http://stackoverflow.com/questions/1625327/editorfor-and-html-properties). Or if you really want something for only one situation you can use a [partial view](http://stackoverflow.com/questions/13934671/using-partial-views-in-asp-net-mvc-4) instead of `EditorFor`. – smoksnes Oct 12 '16 at 05:44