2009-10-01 18 views
3

Comment puis-je fournir une forme d'attribut par rapport à mes objets métier dans mon application ASP.Net MVC afin de pouvoir récupérer les textes d'aide dans la vue et ont leur apparaissent comme des textes d'aide en vol stationnaire pop-up comme celui-ci:Comment ajouter des attributs d'invite d'aide à Business Objects dans MVC et afficher dans la vue

<%= Html.TextBox("PostalCode", Model.PostalCode, new { 
    title = "Please enter your postal code." })%> 

Je veux être en mesure d'obtenir la valeur « titre » de mon ViewModel qui aura ramassé le texte à partir d'un attribut sur l'objet d'affaires. En résumé, comment puis-je appliquer des attributs/métadonnées de texte d'aide sur mes Business Objects?

+0

En fin de compte j'ai affiné mon exigence en tenant compte du fait que la nécessité était d'appliquer le texte d'aide (info-bulle) à l'interface utilisateur, mais avoir ces infobulles à la fois localisées et accessibles/gérées à partir de la zone des entités commerciales réutilisables (pour utilisation dans la mise en œuvre ultérieure de l'interface utilisateur à l'aide des services RIA). – Redeemed1

Répondre

2

Voici comment je l'ai fait:

  1. Créé nouvel attribut comme suit:

    public class HelpPromptAttribute : Attribute 
    { 
        public HelpPromptAttribute(string text) 
        { 
         myproperty = text; 
        } 
        protected string myproperty; 
    
        public string HelpTextKey 
        { 
         get { return myproperty; } 
         set { myproperty = value; } 
        } 
    } 
    
  2. attribut Ajouté à la propriété d'entité comme suit:

    [HelpPrompt("ProjectDescription")] 
    [Required(ErrorMessageResourceName = "ProjectDescriptionRequired", ErrorMessageResourceType = typeof(EntityValidationMessages))] 
    [StringLength(50, ErrorMessageResourceName = "ProjectDescriptionTooLong", ErrorMessageResourceType = typeof(EntityValidationMessages))] 
    public string ProjectDescription { get; set; } 
    
  3. Ajouté Extension Méthode aux entités comme suit:

    public static class EntityBOExtensions 
    { 
        public static string PropertyHelp(this object objectBO, string PropertyName) 
        { 
         Type type = objectBO.GetType(); 
    
    
         foreach (PropertyInfo pInfo in type.GetProperties()) 
         { 
          if (string.Compare(pInfo.Name, PropertyName) == 0) 
          { 
           foreach (Attribute attr in Attribute.GetCustomAttributes(pInfo)) 
           { 
            if (attr.GetType() == typeof(HelpPromptAttribute)) 
            { 
             string key = ((HelpPromptAttribute)attr).HelpTextKey; 
             if (!string.IsNullOrEmpty(key)) 
              return EntityBOHelp.ResourceManager.GetString(key); 
            } 
           } 
          } 
         } 
         return null; 
        } 
    } 
    
  4. Ajout d'une HtmlHelper (simple) comme suit:

    public static string LocalisedTextBoxWithHelp(this HtmlHelper helper, string name, object value, string helptext) 
    { 
        string textbox = helper.TextBox(name, value, new { helpprompt = helptext }); 
        return textbox; 
    } 
    
  5. Et finalement utilisé le balisage folowing dans la vue:

    <%= Html.LocalisedTextBoxWithHelp("project.ProjectDescription", Model.ProjectDescription, Model.PropertyHelp("ProjectDescription"))%> 
    

Ce fait le travail bien qu'il a besoin de raffinement. ;)

1

Mise à jour:

Vous pouvez simplement créer une nouvelle propriété de classe pour chacun de votre objet nommé « Titre » ou « Conseil » et ajoutez la valeur de chaîne appropriée pour eux. Puis obtenir cette propriété avec MyObject.Title


Question intéressante. Je voudrais voir une réponse à cela en utilisant les attributs, mais voici deux méthodes que je peux penser:

Ajouter une méthode d'extension à vos objets Cela nécessiterait beaucoup de codes répétitif.

public static string GetTitle(this YourObject obj) 
{ 
    return "Title for object"; 
} 

Html méthode d'extension Helper

Vous stocker les titres d'objet dans cette méthode d'aide.

public static string GetObjectTitle(this HtmlHelper html, string type) 
{ 
    switch(type) 
    { 
      case "Object1": 
      return "Title for object 1"; 
      break; 

      case "Object2": 
      return "Title for object 2"; 
      break; 

      default: 
      return "No titled specified for this object type"; 
      break; 
    } 
} 

Pour appeler cette méthode:

<%= Html.GetObjectTitle(Model.GetType()) %> 

Ou dans votre exemple:

<%= Html.TextBox("PostalCode", Model.PostalCode, new { 
watermark = "Postal Code", 
title = Html.GetObjectTitle(Model.GetType()) })%> 

Je préfère la 2ème méthode parce que vous avez un endroit pour stocker tous les titres et vous auriez besoin écrire moins de code.

Cependant, je pense qu'ajouter un attribut à la classe et créer un moyen d'obtenir cet attribut fonctionnerait un peu mieux.

+0

Pourquoi utiliseriez-vous des méthodes d'extension quand vous pouvez simplement mettre la méthode directement dans la classe, et l'appeler directement? –

+0

La déclaration de cas est pire. Il casse l'encapsulation en vous obligeant à définir le message quelque part en dehors de l'objet métier. –

+0

L'une ou l'autre méthode casserait «insérer un terme de conception de programme pédant» dans une certaine mesure. Je préfère la déclaration de cas car elle placerait tous les titres au même endroit, ce qui faciliterait les futures éditions.Theres certainement de meilleurs moyens de le faire, je ne peux tout simplement pas penser à eux. En y réfléchissant maintenant, vous pourriez spécifier une propriété "Titre" pour chaque objet, et selon la façon dont votre application est configurée, cela pourrait être la meilleure chose. – Omar

1

Je ne pense pas qu'il existe un moyen de le faire dès la sortie de la boîte. Cependant, vous pouvez créer une classe générique de «valeur de modèle» qui encapsule cette information dans la classe, ce qui vous permet de conserver votre vue fortement typée. Par exemple:

ModelValue<string> postalCode = new ModelValue<string>("poscode value", "Please enter your postal code.") 

Vous pouvez ensuite créer vos classes de modèle pour qu'elles contiennent les propriétés de type ModelValue.

Votre code ci-dessus serait alors ressembler à:

<%= Html.TextBox("PostalCode", Model.PostalCode.Value, new {  watermark = "Postal Code",  title = Model.PostalCode.Title })%> 

L'inconvénient de le faire est que je ne pense pas que mvc va faire automatique obligatoire pour vous, alors vous aurez à faire Tout le mapping dans la vue vous-même, comme dans cet exemple mais aussi sur Post, vous devrez faire une reliure manuelle si vous ne l'avez pas déjà fait. Vous instanciez probablement toutes vos propriétés ModelValue dans le constructeur du modèle et récupérez toutes les valeurs de titre de leur stockage, car vous ne les relieriez pas sur Post (je pense aux erreurs de validation qui provoquent le formulaire à être réaffiché). Si vous étiez super désireux, vous mettriez des attributs sur les propriétés de votre modèle et les analyseriez en quelque sorte lorsque vous restituerez la page, mais je ne sais pas par où commencer si vous voulez aller de cette façon.

+0

en fait, c'est l'idée d'attributs sur les propriétés du modèle que je cherche. Je pense qu'il y a peut-être quelque chose dans EnterpriseLibrary mais je serais tout aussi content de savoir que je pourrais même définir des attributs personnalisés et simplement les appliquer au modèle – Redeemed1

1

Je sais que c'est ancien, mais j'ai récemment fait face à ce problème avec un projet ASP.NET MVC3 et implémenté une solution.

1. Créez un attribut personnalisé pour stocker le texte d'aide

public class HelpTextAttribute : DescriptionAttribute 
{ 
    public HelpTextAttribute(string helpText) 
     : base(helpText) 
    { } 
} 

2. Créer une méthode d'extension HtmlHelper pour récupérer la valeur d'attribut

public static class HtmlHelperExtensions 
{ 
    public static string HelpTextFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
    { 
     var memberExpression = expression.Body as MemberExpression; 
     if (memberExpression == null) 
      throw new InvalidOperationException("Expression must be a member expression"); 

     var attributes = memberExpression.Member.GetCustomAttributes(typeof(HelpTextAttribute), true); 
     var attribute = attributes.Length > 0 ? attributes[0] as HelpTextAttribute : null; 

     return html.Encode(attribute == null ? string.Empty : attribute.Description); 
    } 
} 

3. annoter les Propriété de modèle avec l'attribut HelpText

[HelpText("A level from which to start")] 
[Required("You must select a level")] 
public int Level { get; set; } 

4. Utilisez simplement la nouvelle méthode d'extension HtmlHelper avec votre vue

<div class="editor-help"> 
    <%: Html.HelpTextFor(model => model.Level) %> 
</div>