0

I'm trying to create my own HTML helper method with this syntax:

@Html.BootstrapLabelFor(m => Model.Email) //Email is a simple string property.

Here is what I have so far:

public static MvcHtmlString BootstrapLabelFor<TModel, TValue>
(this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TValue>> expression)
{
    string html = String.Format("<label for='{0}' class='some-class' />",
        expression.Email.DisplayName???? - NEED HELP HERE. );
    return new MvcHtmlString(html);
}

So here the gist of it.

What I need to know is how to fetch the DisplayName property (if it's called that) from within the expression object. Assuming that's where I need to look.

Here is my LogOnModel class:

public class LogOnModel
{
    [Required(ErrorMessage = "You must enter your email address.")]
    [Display(Name = "Email:")]
    public string Email { get; set; }

    [Required(ErrorMessage = "You must enter your password.")]
    [DataType(DataType.Password)]
    [Display(Name = "Password:")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}

Now we're getting somewhere. Here's what I have now. It's outputting the correct property with what I want, but it's not using the DisplayName metadata decorator I used in the model. Only spitting out the property name. Any suggestions?

public static MvcHtmlString BootstrapLabelFor<TModel, TValue>
    (this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TValue>> expression)
{
    string html = String.Format(
        "<label for='{0}' class='control-label'>{0}</label>",
        ExpressionHelper.GetExpressionText(expression));
    return new MvcHtmlString(html);
}
Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
Only Bolivian Here
  • 35,719
  • 63
  • 161
  • 257
  • I'm confused.... it should be `Expresion>` where `TModel` is your model and `TValue` is implied by the projection... exactly what it says...? – Marc Gravell Mar 13 '12 at 20:15

1 Answers1

1

Have a look at the ASP.Net MVC 3 source-code and copy what they are doing, you'd end up with something a bit like this:

public static MvcHtmlString BootstrapLabelFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper,
                                                            Expression<Func<TModel, TValue>> expression)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var htmlFieldName = ExpressionHelper.GetExpressionText(expression);
    var resolvedLabelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
    if (String.IsNullOrEmpty(resolvedLabelText))
    {
        return MvcHtmlString.Empty;
    }

    TagBuilder tag = new TagBuilder("label");
    tag.Attributes.Add("for", TagBuilder.CreateSanitizedId(htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName)));
    tag.Attributes.Add("class", "control-label");
    tag.SetInnerText(resolvedLabelText);
    return new MvcHtmlString(tag.ToString(TagRenderMode.Normal));
}

Unfortunately, the built in helper methods for Labels don't accept htmlAttributes, so you can't easily reuse their code for this.

StanK
  • 4,750
  • 2
  • 22
  • 46