Problem accessing DisplayAttribute on Razor Page - Is it Me or Mercury?

Version 11.0.0.2719

I have a model class that uses a DisplayAttribute DataAnnotation. I’m trying to retrieve information in that DisplayAttribute in Mercury, similar to this StackOverflow example. But I get a compile error. Am I doing something wrong, or is it Mercury?

Here is my Extensions class:

Public Class Extensions
  Public Shared Function GetDescription(Of T As Class)(ByVal propertyName As String) As String
    Dim memberInfo As MemberInfo = GetType(T).GetProperty(propertyName)

    If memberInfo Is Nothing Then
      Return Nothing
    End If

    Return memberInfo.GetCustomAttribute(Of DisplayAttribute)()?.GetDescription()
  End Function

End Class

Here is how it looks on my Razor Page:
<input type="text" asp-for="CurrentToDo.Name" placeholder="Name" title='@Extensions.GetDescription(Of ToDoModel)("Name")' />

I’ve also tried it this way, per the solution comment:
<input type="text" asp-for="CurrentToDo.Name" placeholder="Name" title='(@Extensions.GetDescription(Of ToDoModel)("Name"))' />

The error I get in either case is “comma or closing parenthesis expected”:

Also, as an aside: The “Paste & Convert C# Code” for the Shared Function did not handle this code very well. Here’s the result, which swallowed the “(Of T As Class)” part and also split the return line into multiple lines that aren’t quite right:

Public Shared Class Extensions

  Public Function GetDescription(propertyName As String) As String
    Dim memberInfo As MemberInfo = GetType(T).GetProperty(propertyName)
    If (memberInfo) Is Null Then
      Return Null
    End If
    If memberInfo.GetCustomAttribute(Of DisplayAttribute)() IsNot Nothing Then
      GetDescription()
      result = memberInfo.GetCustomAttribute(Of DisplayAttribute)()
    End If
    Return
  End Function

End Class

Thanks,

–Avonelle

Any chance I could see a full project to have a look at?

Here you go.
ASPNetCoreEmptyProjectTestVS2019.zip (1.5 MB)

–Avonelle

1 Like

Ah yes. note that .cshtml files generate C# code behind, not VB. so tie get

…/EBuild/Obj/ASPNetCoreEmptyProjectTestVS2019-F326B6961E4B43781E8597C04878795E423EA1BE.Views/Debug/Echoes/Razor/Pages/AddToDo.cshtml.cs

which contains

#line 13 "/Users/mh/Downloads/ASPNetCoreEmptyProjectTestVS2019/ASPNetCoreEmptyProjectTestVS2019/Pages/AddToDo.cshtml"
AddHtmlAttributeValue("", 381, Extensions.GetDescription(Of ToDoModel)("Name"), 381, 48, false);

and off course thats not valid C#.

I would call this as-designed; you need to use C# generics syntax for this in .cshtml, not Mercury.

Oh, DUH, I knew that, and totally forgot. Sorry.

However, I’m still having trouble getting the syntax right. I’ve tried this:
<input type="text" asp-for="CurrentToDo.Name" placeholder="Name" title='(@Extensions.GetDescription<ToDoModel>("Name"))' />

and this:
<input type="text" asp-for="CurrentToDo.Name" placeholder="Name" title='@Extensions.GetDescription<ToDoModel>("Name")' />

But I still get the same error. Maybe I’m not implementing the C# syntax properly?

–Avonelle

You’ll wanna drop the @, i’m not sure what it does in VB, but it’s not valid for C#… without it, it compiles ok for me.

FWIW, slightly tangential, i have also hooked up the option to toggle between Original and Generated file in Fire/Water now, for Razor (which was a tad bit more complicated than for other code-behind cases, for reasons):

Hmmmmm…you are right, it does compile without that, but it doesn’t work. It is supposed to make the tool the description of the Display attribute for that property, but it is not.
image

That “@” isn’t VB code, that is ASP.NET Razor syntax:
ASP.NET Razor C# Syntax

–Avonelle

Ok, but are you sure that supported in these HTML attributes? it seems they ALREADY get treated as C#, even without the @. Also, wouldn’t it need to be outside of the (), at least?

I gotta admit i don;'t know much about how this stuff works, but the cshtml-to-cs conversion is all handled Microsoft’s tool and out of our control…

That said, without the @ it does generate the code i would expect?/

#line 13 "/Users/mh/Downloads/ASPNetCoreEmptyProjectTestVS2019 2/ASPNetCoreEmptyProjectTestVS2019/Pages/AddToDo.cshtml"
AddHtmlAttributeValue("", 380, Extensions.GetDescription<ToDoModel>("Name"), 380, 47, false);

so if that doesn’t work, maybe that is an issue elsewhere?

Wait, sorry, no that’s with

title='@(Extensions.GetDescription<ToDoModel>("Name"))'

]withoiut the @ it only generated the whole thing as static string.

private static readonly global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute __tagHelperAttribute_4 = new global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute("title", new global::Microsoft.AspNetCore.Html.HtmlString("(Extensions.GetDescription<ToDoModel>(\"Name\"))"), global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.SingleQuotes);

so i was right, the @ needs to be outside the ().

If it’s not, only a suelse only a sub-portion of the attribute gets treated as C# expression, and it stops at the <.:

AddHtmlAttributeValue("", 381, Extensions.GetDescription, 381, 26, false);
...
                AddHtmlAttributeValue("", 407, "<ToDoModel>(\"Name\"))", 407, 20, true);

May i say that this syntax is f*ed up?

Yeah, it isn’t exactly how I would have designed it, either!

Ugh. The syntax I ended up with that compiles is:

@{(Extensions.GetDescription<ToDoModel>("Name"));}

And with some tweaks to the Extensions code, it returns what I want:

However, the result isn’t rendering on the page. No errors - it just doesn’t work.

So I tried creating a C# test project to test out the original StackOverflow sample I was using, and I can’t get that to work either. So this whole approach was based on some sample code that apparently doesn’t work. :frowning:

Oh well, I learned some things in the process! But sorry to take you down this winding road just to come back to square one.

I’m sure that will be very useful, thanks!

–Avonelle

:joy: Welcome to Strack Overflow…

it kind of akes sense they cant support geenrics without (), because they want to supportt, say

@Foo<b>@Bar</b>

and that’d be ambiguous/tricky to parse/detect — is “b” a new HTML tag or a generic parameter? But still… nasty.

:raised_hands:t3:

Granted, although I’ve generally had good luck with solutions I find there. Might not be the BEST solution, but typically it works. Then again, I’ve been living a long time in the VB.NET and ASP.NET WebForms world, where things don’t change that much, unlike the constant churn of this .NET Core shi…ummm STUFF.

–Avonelle

:upside_down_face: