Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC6 alternative to @Html.DisplayFor

MVC6 introduces Tag Helpers which is a better way compared to using @Html.EditorFor, etc. However I have not found any Tag Helper that would be an alternative to @Html.DisplayFor.

Of course I can use a variable directly on a Razor page, such as @Model.BookingCode. But this does not allow to control formatting.

With MVC6, what's conceptually correct way for displaying a value of a model property?

like image 573
Sergey Kandaurov Avatar asked Sep 19 '15 18:09

Sergey Kandaurov


People also ask

What is the difference between tag helper and HTML helper?

Tag Helpers are attached to HTML elements inside your Razor views and can help you write markup that is both cleaner and easier to read than the traditional HTML Helpers. HTML Helpers, on the other hand, are invoked as methods that are mixed with HTML inside your Razor views.

What is HTML DisplayFor?

DisplayFor() The DisplayFor() helper method is a strongly typed extension method. It generates a html string for the model object property specified using a lambda expression.

Which tag helper is used to perform model binding?

The Input Tag Helper binds an HTML <input> element to a model expression in your razor view.


3 Answers

@Html.DisplayFor still exists and can still be used.

The difference between HtmlHelpers and TagHelpers is that HtmlHelpers choose which html elements to render for you whereas TagHelpers work with html tags that you add yourself so you have more full control over what html element is used. You do have some control over the markup using templates with HtmlHelpers but you have more control with TagHelpers.

So you should think in terms of what html markup do I want to wrap this model property in and add that markup around the property itself using @Model.Property with some markup around it or continue using DisplayFor if you prefer to let the helper decide.

like image 155
Joe Audette Avatar answered Nov 18 '22 14:11

Joe Audette


You can create your own tag helper

namespace MyDemo.TagHelpers
{
    [HtmlTargetElement("p", Attributes = ForAttributeName)]
    public class DisplayForTagHelper : TagHelper
    {
        private const string ForAttributeName = "asp-for";

        [HtmlAttributeName(ForAttributeName)]
        public ModelExpression For { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            var text = For.ModelExplorer.GetSimpleDisplayText();

            output.Content.SetContent(text);
        }
    }
}

Add use it in view:

<p asp-for="MyProperty" class="form-control-static"></p>
like image 34
WeHaveCookies Avatar answered Nov 18 '22 13:11

WeHaveCookies


I have been using this as a display tag helper.

[HtmlTargetElement("*", Attributes = ForAttributeName)]
public class DisplayForTagHelper : TagHelper
{
    private const string ForAttributeName = "asp-display-for";
    private readonly IHtmlHelper _html;

    public DisplayForTagHelper(IHtmlHelper html)
    {
        _html = html;
    }

    [HtmlAttributeName(ForAttributeName)]
    public ModelExpression Expression { get; set; }

    public IHtmlHelper Html
    {
        get
        {
            (_html as IViewContextAware)?.Contextualize(ViewContext);
            return _html;
        }
    }

    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));
        if (output == null)
            throw new ArgumentNullException(nameof(output));

        var type = Expression.Metadata.UnderlyingOrModelType;
        if (type.IsPrimitive)
        {
            output.Content.SetContent(Expression.ModelExplorer.GetSimpleDisplayText());
        }
        // Special Case for Personal Use
        else if (typeof(Dictionary<string, string>).IsAssignableFrom(type))
        {
            output.Content.SetHtmlContent(Html?.Partial("Dictionary", Expression.ModelExplorer.Model));
        }
        else
        {
            var htmlContent = Html.GetHtmlContent(Expression);
            output.Content.SetHtmlContent(htmlContent);
        }
    }
}

public static class ModelExpressionExtensions
{
    public static IHtmlContent GetHtmlContent(this IHtmlHelper html, ModelExpression expression)
    {
        var ViewEngine = html.ViewContext.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
        var BufferScope = html.GetFieldValue<IViewBufferScope>();
        var htmlContent = new TemplateBuilder(ViewEngine, BufferScope, html.ViewContext, html.ViewContext.ViewData, expression.ModelExplorer, expression.Name, null, true, null).Build();
        return htmlContent;
    }

    public static TValue GetFieldValue<TValue>(this object instance)
    {
        var type = instance.GetType(); 
        var field = type.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).FirstOrDefault(e => typeof(TValue).IsAssignableFrom(e.FieldType));
        return (TValue)field?.GetValue(instance);
    }
}
like image 39
Rahma Samaroon Avatar answered Nov 18 '22 15:11

Rahma Samaroon