9

I am working on a project with a huge number of data tables and displaying them through ASP.net MVC screens.

I find myself writing a lot of simple data annotations like this:

 [Display(Name = "Manager Name")]
 public string ManagerName { get; set; }

 [Display(Name = "Employee Name")]
 public string EmployeeName { get; set; }

 [Display(Name = "Employee No")]
 public string EmployeeNo { get; set; }

 [Display(Name = "Manager Employee No")]
 public string ManagerEmployeeNo { get; set; }

This is getting quite tedious and was wondering if there is a way that I can either add a new attribute that says "convertFromCamel" (or something) or is there a way to override

 @Html.DisplayNameFor(m => Model.First().EmployeeNo)

So that if there is no data annotation it converts the existing field name from camel case.

thanks in advance

Lobsterpants
  • 1,188
  • 2
  • 13
  • 33
  • 2
    Its not a data annotation you need, its a custom DataAnnotationsModelMetadataProvider where you override `CreateMetadata()` to set the ModelMetatdata.DisplayName property –  May 21 '15 at 08:42

1 Answers1

10

Using a combination of the information found on the blog here, and the excellent camel-case split regex here, I was able to work this out. The concept is that you create a custom flavour of the default DataAnnotationsModelMetadataProvider. In the case where a property does not have a display name already, this custom provider kicks in and creates one for you (with spaces).

First, create a class:

using System;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Web.Mvc;

namespace MyProject.Whatever
{
    public class CustomDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
    {
        protected override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, PropertyDescriptor propertyDescriptor)
        {
            ModelMetadata metadata = base.GetMetadataForProperty(modelAccessor, containerType, propertyDescriptor);
            if (metadata.DisplayName == null)
            {
                metadata.DisplayName = SplitCamelCase(metadata.GetDisplayName());
            }
            return metadata;
        }

        private string SplitCamelCase(string str)
        {
            return Regex.Replace(
                Regex.Replace(
                    str,
                    @"(\P{Ll})(\P{Ll}\p{Ll})",
                    "$1 $2"
                ),
                @"(\p{Ll})(\P{Ll})",
                "$1 $2"
            );
        }
    }
}

Now override the default DataAnnotationsModelMetadataProvider in your Global.asax.cs file by doing the following:

protected void Application_Start()
{
    //Other stuff.
    ...
    ModelMetadataProviders.Current = new CustomDataAnnotationsModelMetadataProvider();
}
Community
  • 1
  • 1
Jamie Dunstan
  • 3,725
  • 2
  • 24
  • 38