Question

I have a model say

public class Contact
{
    [Display(Name = "Phone Number", Description = "This is Phone number to contact")]
    [Visibility(ShowForDisplay=false)]
    public string Phone { get; set; }

    [Display(Name = "Mail To Support", Description = "This is Mail for support")]
    public string Email { get; set; }
}

Now in Mvc html I m doing at several places like

@Html.DisplayTextFor(x=>x.Phone)

Now I want a attribute based something like this which can manage at model level for turning of this display into the view . Like for eg the @html.DisplayTextFor(x=>x.Phone) should be there but when I do [Visibility(ShowForDisplay=false)] then all the visibility for the values or texts should not be rendered on the html .

How can be done through attribute like custom attribute [Visibility(ShowForDisplay=false)] ?

Was it helpful?

Solution

All Html Helper methods working with Model MetaData, and you can't change ModelMetada class so you should make your own Html helper, and ofcourse you need a custom attribute. Check this code:

First create a custom attribute:

public class VisibilityAttribute : ValidationAttribute
{
    private bool _isVisible;

    public VisibilityAttribute(bool visible = true)
    {
        _isVisible = visible;
    }

    public bool ShowForDisplay
    {
        get
        {
            return _isVisible;
        }
        set
        {
            _isVisible = value;
        }
    }
}

Then create a Html helper:

public static class MyHtmlExtensions
{
    public static MvcHtmlString DisplayTextForCustom<TModel, TResult>(this HtmlHelper<TModel> html,
        Expression<Func<TModel, TResult>> expression)
    {
        ExpressionType type = expression.Body.NodeType;
        if (type == ExpressionType.MemberAccess)
        {
            MemberExpression memberExpression = (MemberExpression) expression.Body;
            PropertyInfo pi = memberExpression.Member as PropertyInfo;

            var attributes = pi.GetCustomAttributes(); 

            foreach (var attribute in attributes)
            {

                if (attribute is VisibilityAttribute)
                {
                    VisibilityAttribute vi = attribute as VisibilityAttribute;
                    if (vi.ShowForDisplay)  
                    {
                        var metadata = ModelMetadata.FromLambdaExpression<TModel, TResult>(expression, html.ViewData);
                        return MvcHtmlString.Create(metadata.SimpleDisplayText);
                    }
                }
            }
        }
        return MvcHtmlString.Create("");
    }
}

Then call it from your View like this:

@Html.DisplayTextForCustom(x=>x.Phone)

PS: To write this code I looked at Html.DisplayTextFor source code and I try to write a code as simple as possible.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top