2011-12-11 3 views
2

J'ai un modèle avec des entités BlogPost et Tag.ASP.NET MVC 3: Modèle Blog Posts Tags Binding Best Practices

public class Tag 
{ 
    public string Name { get; set; } 
    public string Slug { get; set; } 
} 

public class BlogPost : ITaggable 
{ 
    public BlogPost() 
    { 
     this.Tags = new List<Tag>(); 
    } 
    public ICollection<Tag> Tags { get; set; } 
    [AllowHtml] 
    public string Text { get; set; } 
} 

Sur admin Les balises de page d'édition BlogPost doivent être représentées dans une entrée de texte, séparées par une virgule. Assez semblable à l'entrée de la balise StackOverflow.

Cela signifie la sérialisation de ICollection à une chaîne, et la désertification retour à une collection. Je suis content du classeur par défaut, à côté de la collection Tags de BlogPost.

Il y a peu d'options que je connais pour y faire face:

  1. Modèle personnalisé Binder - avec un besoin de passer outre toutes les liaisons Blogpost - il y a vraiment des propriétés du lot dans une entité réelle BlogPost.

  2. Créez une entrée de texte non liée à un modèle BlogPost et obtenez/définissez ses valeurs à l'aide des paramètres de formulaire. Cela nécessite également plus de travail manuel.

  3. Quelque chose d'autre ....

Comment voulez-vous mettre en œuvre l'entrée des tags pour un billet de blog?

MISE À JOUR:

Pour l'instant j'essaie ceci:

public List<Tag> Tags { get; set; } 
public string TagsString { 
    get 
    { 
     var tags = Tags.Select(tg => tg.Name).ToArray(); 
     var res = string.Join(",", tags); 
     return res; 
    } 
    set 
    { 
     var tags = value.Split(','); 
     Tags = new List<Tag>(); 
     foreach (var tag in tags) 
      Tags.Add(new Tag { Name = tag }); 
    } 
} 

Répondre

1

Je maintiendrait l'interface utilisateur/UX pour les montrer séparés par des virgules dans une seule zone de texte.

Pour ce qui est de les obtenir en tant que collection dans le contrôleur, personnellement, je m'en tiendrai au modelbinder par défaut, mais cela ne signifie pas nécessairement que c'est la bonne façon.

Je ferais quelque chose de semblable à votre # 2, mais j'utiliserais un <select multiple="multiple"> pour qu'il y ait 1 <option selected="selected">TagName/Slug</option> élément pour chaque étiquette.

En ce qui concerne le maintien de la dépendance/liaison entre la zone de texte et la liste de sélection multiple, j'utiliserais knockoutjs pour cela. Analysez les virgules dans la zone de texte et mettez à jour le multi-select (caché). En cas de soumission au contrôleur, ignorez la zone de texte (ou ne faites simplement pas partie de votre viewmodel côté serveur).

4

C'est le cas parfait pour introduire un ViewModel entre votre vue et votre modèle.

Un ViewModel vous permettra de modifier la représentation de vos données (les diviser en une chaîne) pour une vue spécifique (c'est une bonne pratique pour en créer une par vue) sans altérer l'intégrité de votre modèle. Ensuite, votre contrôleur sera en charge de la sérialisation/désérialisation.

Voici quelques articles sur le besoin et le comment de ViewModels en ASP.NET applications MVC: