1

I'd want to use in cshtml description of property/field from Description attribute

Is it possible to do it as easily as with DisplayName by using @Html.DisplayNameFor(x => ...) or I have to "extract it"

public class Test
{
    [Description("Test description")]
    public bool Name { get; set; }
}

I've been trying with something like that, but without any success

var desc = typeof(Test)
.GetCustomAttributes(false)
.ToDictionary(a => a.GetType().Name, a => a);

or

typeof(Test).Attributes

typeof(Test).GetCustomAttributesData();
Joelty
  • 1,751
  • 5
  • 22
  • 64
  • 1
    Probably you might want to look for and try solutions for [this issue](https://stackoverflow.com/questions/6578495/how-do-i-display-the-displayattribute-description-attribute-value/18886645), since your `DescriptionAttribute` is essentially used like `DisplayAttribute`. – Tetsuya Yamamoto Mar 27 '19 at 08:46
  • No, there is no way to quickly and easily get the `Description` of a `DescriptionAttribute` - but you can write an extension method on `HtmlHelper` called `DescriptionFor` that encapsulates looking up this metadata. – Ian Kemp Mar 27 '19 at 08:54

2 Answers2

2

You can simply write a custom HtmlHelper for that:

public static class HtmlHelpers
{
    public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        if (expression == null)
            throw new ArgumentNullException(nameof(expression));

        DescriptionAttribute descriptionAttribute = null;
        if (expression.Body is MemberExpression memberExpression)
        {
            descriptionAttribute = memberExpression.Member
                .GetCustomAttributes(typeof(DescriptionAttribute), false)
                .Cast<DescriptionAttribute>()
                .SingleOrDefault();
        }

        return new HtmlString(descriptionAttribute?.Description ?? string.Empty);
    }
}
Moien Tajik
  • 2,115
  • 2
  • 17
  • 39
  • 1
    You should not use `HtmlString` since this will treat the description value as HTML code and not encode special characters that appear within. For example, this will not be escaped but interpreted as html: `[Description("You can add code like ")]` – NineBerry Mar 27 '19 at 10:30
  • The value of that `DescriptionAttribute` is not entered by a client, but you right, it's better to encode its contents. @NineBerry – Moien Tajik Mar 27 '19 at 10:39
  • This probably can do the work for you ``var result = HttpUtility.HtmlEncode(descriptionAttribute?.Description ?? string.Empty);`` – Joelty Mar 27 '19 at 10:45
  • Just return `string` instead of `IHtmlContent`. That is what `DisplayNameFor` does in ASP.net core. ASP.net will then take care of using the correct encoding mechanism. Different encoding will be required depending on where in the HTML source the content is inserted. – NineBerry Mar 27 '19 at 11:13
0

I managed to do it with this code:

public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
    if (html == null) throw new ArgumentNullException(nameof(html));
    if (expression == null) throw new ArgumentNullException(nameof(expression));

    var modelExplorer = ExpressionMetadataProvider.FromLambdaExpression(expression, html.ViewData, html.MetadataProvider);
    if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {ExpressionHelper.GetExpressionText(expression)}");

    var metadata = (DefaultModelMetadata)modelExplorer?.Metadata;

    if (metadata == null)
    {
        return new HtmlString(string.Empty);
    }

    var text = (metadata
                .Attributes
                .Attributes // yes, twice
                .FirstOrDefault(x => x.GetType() == typeof(DescriptionAttribute)) as DescriptionAttribute)
                ?.Description;

     var output = HttpUtility.HtmlEncode(text ?? string.Empty);

     return new HtmlString(output);
}
Joelty
  • 1,751
  • 5
  • 22
  • 64
  • 1
    You should not use `HtmlString` since this will treat the description value as HTML code and not encode special characters that appear within. For example, this will not be escaped but interpreted as html: `[Description("You can add code like ")]` – NineBerry Mar 27 '19 at 10:31
  • @NineBerry Check now ``""`` is changed into ``"<script>alert('test')</script>"`` Probably it's fine now. – Joelty Mar 27 '19 at 10:44
  • Just return `string` instead of `IHtmlContent`. That is what `DisplayNameFor` does in ASP.net core. ASP.net will then take care of using the correct encoding mechanism. Different encoding will be required depending on where in the HTML source the content is inserted. – NineBerry Mar 27 '19 at 11:13
  • @NineBerry ``Cannot implicitly convert type 'string' to 'Microsoft.AspNetCore.Html.IHtmlContent' `` – Joelty Mar 27 '19 at 11:53
  • You need to declare the method to return type string. – NineBerry Mar 27 '19 at 12:25
  • @NineBerry jesus christ, sorry :D – Joelty Mar 27 '19 at 13:26