23

I'm currently building the Admin back-end for a website in ASP.NET MVC.

In an ASP.NET MVC application, I've started using the 'EditorFor' helper method like so:

<div id="content-edit" class="data-form">
    <p>
        <%= Html.LabelFor(c => c.Title) %>
        <%= Html.TextBoxFor(c => c.Title)%>
    </p>
    <p>
        <%= Html.LabelFor(c => c.Biography) %>
        <%= Html.EditorFor(c => c. Biography)%>
    </p>
</div>

In the model, the 'Biography' field has been decorated with: [UIHelper("Html")].

I have an 'Html' partial view (under Views/Shared/EditorTemplates):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.XML.Linq.XElement>" %>

<textarea class="html">
    <%= Model.ToString() %>
</textarea>

Now I'd like to have the 'ID' attribute of the 'textarea' set to the name of the field, like this:

<textarea id="Biography" class="html">
    ...
</textarea>

But I can't see a way to do that with the current set up.

All I can think of is creating an 'Html' ViewModel that contains a 'Value' property and a 'ControlID' property.

But if I based the view off that, rather than 'System.XML.Linq.XElement', it would no longer be compatible with the 'EditorFor' helper method and I'd have to do everything manually.

Has anyone had a similar problem yet?

IAdapter
  • 62,595
  • 73
  • 179
  • 242
Jonathan
  • 32,202
  • 38
  • 137
  • 208
  • Just found a similar question being asked by @nathan-taylor: http://stackoverflow.com/questions/1329148/asp-net-mvc-solution-layout-suggestions – Jonathan Sep 27 '09 at 06:25
  • 1
    That question doesn't appear to have anything to do with this one. Did you paste the wrong link? – Ryan Lundy Feb 15 '12 at 15:55

3 Answers3

37

You should be able to pull out the desired ID from the ViewData.TemplateInfo.HtmlFieldPrefix property of the view. Like this:

<%@ Control Language="C#"
      Inherits="System.Web.Mvc.ViewUserControl<System.XML.Linq.XElement>" %>
<textarea id="<%= ViewData.TemplateInfo.HtmlFieldPrefix %>" class="html">
    <%= Model.ToString() %>
</textarea>

To show why this works, here's the place in TemplateHelpers.cs (of MVC2 Preview 1 source) where ViewData is initialized for the Editor template control:

ViewDataDictionary viewData = new ViewDataDictionary(html.ViewDataContainer.ViewData) {
    Model = modelValue,
    TemplateInfo = new TemplateInfo {
        FormattedModelValue = formattedModelValue,
        ModelType = modelType,
        HtmlFieldPrefix = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(expression),
        IsNullableValueType = (underlyingNullableType != null),
    }
};

In the call above, "expression" is initialized (further up the call stack) with the name of the property being edited.

BTW, @Sperling below caught a detail I originally missed: if you're using (or might use) a non-default HtmlHelper.IdAttributeDotReplacement, then you'll want to replace the dots in the HtmlPrefix property with HtmlHelper.IdAttributeDotReplacement.

Justin Grant
  • 44,807
  • 15
  • 124
  • 208
  • 3
    This is not a valid solution in the case of nested collection model. In that case ```HtmlFieldPrefix``` returns ```collectionModel[index].{PropertyName}``` but by default MVC creates id in a format ```collectionModel_{index}__{PropertyName}```. So it is safe to use ```ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty)``` instead of ```HtmlFieldPrefix``` – Rajeesh Apr 01 '13 at 05:41
4

Have been using this to generate id(with model prefix). Skip the .Replace() part if you want the name attribute.

<%=Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(String.Empty).Replace(".", HtmlHelper.IdAttributeDotReplacement) %>
Sperling
  • 171
  • 5
  • this works too, but you don't actually need GetFullHtmlFieldId-- if you look at that method's implementation, if its argument is String.Empty, it simply returns the value of the HtmlFieldPrefix property. – Justin Grant Sep 30 '09 at 15:39
0

In our case we had to use Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName with ExpressionHelper.GetExpressionText

which in razor was used like this:

           // hiddenFor was caching the value of this html input, and the value alone, nothing else on the page!
            Expression<Func<Web.ViewModels.ApiSettingsViewModel, int>> expression = (m => m.OrgApiLoginCredentials[i].OrgApiLoginId); 
        }
        <input type="hidden" value="@Model.OrgApiLoginCredentials[i].OrgApiLoginId" name="@Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression))" class="data-org-api-login-id"/>
Maslow
  • 18,464
  • 20
  • 106
  • 193