3
votes

Remplacer l'annotation du nom d'affichage du modèle MVC avec une fonctionnalité personnalisée

J'ai la méthode suivante où je lis à partir d'un fichier XML clé-valeur. Je passe une clé et je reçois une valeur que j'avais l'habitude d'afficher sur ma vue.

[DisplaySiteText("ReferenceCodeKey")]
public string ReferenceCode { get; set; }

Fondamentalement, je veux pouvoir utiliser cette méthode dans ma classe de modèle comme une annotation de données qui sera extraite directement du fichier texte de mon site et définie sur la propriété du nom d'affichage.

Par exemple, je veux remplacer

[Display(Name = "Reference Code")]
public string ReferenceCode { get; set; }

Par ceci

public static class TextManager
{
    public static string GetValue(string key)
    {
        string returnVal = null; 
        XmlSerializer serializer = new XmlSerializer(typeof(Entries));
        string path = HttpContext.Current.Server.MapPath("/App_Data/text-key-value.xml");
        if (File.Exists(path))
        {
            Entries entries = (Entries)serializer.Deserialize(File.OpenRead(path));
            var entry = entries.Where(u => u.Key == key).FirstOrDefault();
            if (entry != null)
            {
                returnVal = entry.Value;
            }
        }
        return returnVal;
    }
}

DisplaySiteText passerait la chaîne référence "ReferenceCodeKey" à la méthode GetValue, enregistrez la référence dans le fichier, puis définissez l'attribut de nom d'affichage standard sur ce qui se trouvait dans le fichier.

Comment créer ma propre annotation de modèle personnalisé pour ce faire, j'ai écrit des annotations de validation personnalisées dans le passé en créant une classe qui hérite de ValidationAttribute, mais je ne pense pas que cela fonctionnera dans ce cas Cas.


3 commentaires

Je pense que vous auriez juste besoin d'un attribut régulier (par opposition à un ValidationAttribute). DisplaySiteText: Attribute pour définir la clé, puis utilisez une méthode d'extension pour obtenir la valeur de la clé et renvoyer l'appel TextManager.GetValue


Cela fonctionne et c'est un début, mais comment définir exactement la valeur du nom d'affichage à partir de l'appel DisplaySiteText?


De la même manière que vous pouvez créer un nouvel ValidationAttribute , vous pouvez créer un nouvel attribut de métadonnées en dérivant de l'interface IMetadataAware . Vous avez également la possibilité d'utiliser les attributs existants en créant un nouveau fournisseur de métadonnées en dérivant de DataAnnotationsModelMetadataProvider . J'ai décrit les options dans la réponse .


3 Réponses :


1
votes

Peut-être que votre attribut DisplaySiteText pourrait hériter de l'attribut Display et définir le nom en utilisant votre classe d'assistance. Quelque chose comme ceci:

public class DisplaySiteTextAttribute : DisplayAttribute
{
    public DisplaySiteTextAttribute(string key)
    {
        Name = TextManager.GetValue(key);
    }
}


1 commentaires

Je viens d'essayer mais le compilateur répond que DisplayAttribute est scellé.



5
votes

Vous pouvez hériter de DisplayNameAttribute à cette fin

public class DisplaySiteTextAttribute : DisplayNameAttribute
{
    private string _key;

    public DisplaySiteTextAttribute(string key)
    {
        _key = key;
    }

    public override string DisplayName
    {
        get
        {
            return TextManager.GetValue(_key);
        }
    }
}


1 commentaires

Votre constructeur n'est pas nommé correctement, il doit être nommé DisplaySiteTextAttribute au lieu de ResourceDisplayAttribute.



4
votes

Il existe plusieurs options pour personnaliser les métadonnées du modèle:

La troisième option a été discutée dans l'autre réponse. Ici, dans cet article, je vais partager les première et deuxième options.

Option 1 - Personnalisez la façon dont le framework fournit des métadonnées

Vous pouvez changer la logique d'obtention du texte d'affichage sans changer le attribut.

En fait, il est de la responsabilité de ModelMetaDataProvider d'obtenir les données mete pour le modèle, y compris le texte d'affichage des propriétés. Ainsi, en option, vous pouvez conserver l'attribut Display intact et à la place, créer un nouveau fournisseur de métadonnées de modèle et renvoyer des métadonnées de propriété à partir d'une source différente.

Pour ce faire, vous pouvez créer un nouveau fournisseur de métadonnées en dérivant de DataAnnotationsModelMetadataProvider . Remplacez ensuite GetMetadataForProperty et appelez base pour obtenir des métadonnées. Puis modifiez DisplayName en fonction de votre logique en lisant votre gestionnaire de texte.

Vous devez également enregistrer le nouveau fournisseur de métadonnées en tant que ModelMetadataProviders.Current dans App_Start.

using System;
using System.Web.Mvc;
public class CustomMetadataAttribure : Attribute, IMetadataAware
{
    public string Key { get; set; }
    public CustomMetadataAttribure(string key) => this.Key = key;
    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.DisplayName = TextManager.GetValue(this.Key);
    }
}


0 commentaires