How to hookup Humanizer for ASP.NET Core Razor Pages?

545 Views Asked by At

I'm fairly new to ASP.NET Core Razor Pages and I'm trying to hook up the Humanizer framework into the Razor Pages view pipeline using IDisplayMetadataProvider. I'd like for all of my views to transform my model properties to "title case" strings on my labels.

For example, I'd like to do something like this:

public class Person
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

With the class definition above, I'd like for my labels to automatically use the Humanizer To.TitleCase for anytime I say @Html.DisplayNameFor(...):

<div>
   @Html.DisplayNameFor(m => m.FirstName)
   @Html.DisplayFor(m => m.FirstName)
</div>

<div>
   @Html.DisplayNameFor(m => m.LastName): @Html.DisplayFor(m => m.LastName)
</div>

I'd expect to see:

   First Name: Joe
   Last Name: Smith

Solution (UPDATED)

I was able to configure this in classic ASP.NET MVC using the tutorial at the bottom of the Humanizer Readme page (explained here). After looking around the web for a while, I did find this post from Michael Whelan:

public class HumanizerMetadataProvider : IDisplayMetadataProvider
{
    public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
    {
        var propertyAttributes = context.Attributes;
        var modelMetadata = context.DisplayMetadata;
        var propertyName = context.Key.Name;

        if (IsTransformRequired(propertyName, modelMetadata, propertyAttributes))
            modelMetadata.DisplayName = () => propertyName.Humanize().Transform(To.TitleCase);
    }

    private static bool IsTransformRequired(string propertyName, DisplayMetadata modelMetaData, IReadOnlyList<object> propertyAttributes)
    {
        if (!string.IsNullOrEmpty(modelMetaData.SimpleDisplayProperty))
            return false;

        if (propertyAttributes.OfType<DisplayNameAttribute>().Any())
            return false;

        if (propertyAttributes.OfType<DisplayAttribute>().Any())
            return false;

        if (string.IsNullOrEmpty(propertyName))
            return false;

        return true;
    }
}

It took a little different approach with an interface, rather than inheriting from a class. This was the trick to hook into the pipeline for ASP.NET Core Razor Pages. Here was the code needed in the Startup.cs ConfigureServices(...) handler:

services
   .AddRazorPages()
   .AddMvcOptions(m => m.ModelMetadataDetailsProviders.Add(new HumanizerMetadataProvider()));

Hope this helps somebody!

1

There are 1 best solutions below

0
On

FOUND IT

This was a PEBCAK issue. ‍♂️

The fix was here:

  if (!string.IsNullOrEmpty(modelMetaData.SimpleDisplayProperty))
      return false;

Once the if statement was fixed, the "First Attempt" worked as expected.