How can I use a HTML helper method in an extension

2020-02-12 11:03发布

问题:

I have the following classes:

public class Note
{
    public string Text { get; set; }
    public RowInfo RowInfo { get; set; }
}

public class RowInfo
{
    [DisplayName("Created")]
    public DateTime Created { get; set; }
    [DisplayName("Modified")]
    public DateTime Modified { get; set; }
}

In my view I have the following which creates HTML with the correct name and value:

Html.HiddenFor(model => model.Note.Created)

Now what I am trying to do is to create an extension method that will include the above and that I can call in each view. I have tried doing the following. I think I am on the right track but I don't know how to do the equivalent of "model => model.Note.Created" Can someone give me some advice on how I can do this and what I would need to replace the text inside the parenthesis with. I don't have a model but I can do this some other way so the hidden field will go look at my class to get the correct DisplayName just like it does above?

 namespace ST.WebUx.Helpers.Html
   {
    using System.Web.Mvc;
    using System.Web.Mvc.Html
    using System.Linq;

public static class StatusExtensions
{
    public static MvcHtmlString StatusBox(this HtmlHelper helper, RowInfo RowInfo )
    {
        return new MvcHtmlString( 
           "Some things here ... " +
           System.Web.Mvc.Html.InputExtensions.Hidden( for created field ) +
           System.Web.Mvc.Html.InputExtensions.Hidden( for modified field ) );
    }

}

回答1:

You could write a strongly typed helper taking a λ-expression:

public static class StatusExtensions
{
    public static IHtmlString StatusBox<TModel, TProperty>(
        this HtmlHelper<TModel> helper, 
        Expression<Func<TModel, TProperty>> ex
    )
    {
        return new HtmlString(
           "Some things here ... " +
           helper.HiddenFor(ex));
    }
}

and then:

@Html.StatusBox(model => model.RowInfo.Created)

UPDATE:

As requested in the comments section here's a revised version of the helper:

public static class StatusExtensions
{
    public static IHtmlString StatusBox<TModel>(
        this HtmlHelper<TModel> helper,
        Expression<Func<TModel, RowInfo>> ex
    )
    {
        var createdEx = 
            Expression.Lambda<Func<TModel, DateTime>>(
                Expression.Property(ex.Body, "Created"), 
                ex.Parameters
            );
        var modifiedEx =
            Expression.Lambda<Func<TModel, DateTime>>(
                Expression.Property(ex.Body, "Modified"),
                ex.Parameters
            );

        return new HtmlString(
            "Some things here ..." + 
            helper.HiddenFor(createdEx) + 
            helper.HiddenFor(modifiedEx)
        );
    }
}

and then:

@Html.StatusBox(model => model.RowInfo)

Needless to say that custom HTML helpers should be used to generate small portions of HTML. Complexity could grow quickly and in this case I would recommend you using an editor template for the RowInfo type.