Tim
Tim

Reputation: 7421

Custom HtmlHelper for changing labels

i want to provide a method of changing the labels associated with controls which will be rendered on the page via a lookup to a sql table.

Ideally i want to inject the meta data display field which is then rendered on the page using the helper.

@Html.LabelFor(m => m.city)

Since this would need to be a sql lookup at runtime, i cannot just change the class scaffolding tt template to stamp on a displayname annotation at design time.

I thought of 3 potential methods.

  1. rewrite all the html.helpers i want to use. Problem with this is you would need to replicate all the functionality of the existing helper prior to making the changes.

  2. write a custom data annotation and stamp it on each property in the class i.e.

    [MyCustomNameAttribute] public string city{ get; set; }

    then hopefully in the MyCustomNameAttribute class i can find both the linq field i am referring to, a reference to the metadatamodel and a database context using these i can retrieve and replace the DisplayName based on potential name customisations configured by the User. I tried to do this but was unable to find out how the [Display(Name="city")] annotation works in the background.

  3. Modify the entity model backing code to inject the name into the metadatamodel.

Does anyone have any experience of the above?

Cheers Tim

Upvotes: 1

Views: 435

Answers (1)

VJAI
VJAI

Reputation: 32758

You have to create a custom ModelMetaDataProvider by extending the DataAnnotationsModelMetadataProvider.

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes,
        Type containerType,
        Func<object> modelAccessor,
        Type modelType,
        string propertyName)
    {
        var meta = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

               if(meta.DisplayName == null)
               {
                 // TO DO read the display value from database and assign here
                 meta.DisplayName = .. 
               }

        return meta;
    }
}

Then you have to set that in the Global.asax.cs

protected void Application_Start()
{
   RegisterRoutes(RouteTable.Routes);
   ModelMetadataProviders.Current = new CustomModelMetadataProvider();
}

I'm assuming that you want to set only the display name from db but suppose you want to load the complete modelmetadata from db then I would suggest you to create a custom ModelMetadataProvider by implementing the abstract class ModelMetadataProvider.

Hitting the database every time definitely not a good idea so we have to workout for some caching strategy.

We have to hit the database for every new containerType (I guess) and read the metadata information for the container along with all its properties and store in the cache with key as the containerType (this could be a difficult job).

Upvotes: 1

Related Questions