Как добавить атрибуты подсказки в Business Objects в MVC и отобразить в представлении - PullRequest
3 голосов
/ 01 октября 2009

Как я могу предоставить некоторую форму атрибута для моих бизнес-объектов в моем приложении ASP.Net MVC, чтобы я мог подобрать тексты справки в представлении и сделать их всплывающими всплывающими текстами справки, такими как:

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

Я хочу иметь возможность получить значение title из моей ViewModel, которая получит текст из атрибута бизнес-объекта.

В целом, как я могу применить атрибуты / метаданные текста справки к своим бизнес-объектам?

Ответы [ 4 ]

2 голосов
/ 01 октября 2009

Вот как я это сделал:

  1. Создан новый атрибут следующим образом:

    public class HelpPromptAttribute : Attribute
    {
      public HelpPromptAttribute(string text)
      {
          myproperty = text; 
      }
      protected string myproperty;
    
      public string HelpTextKey
      {
          get { return myproperty; }
          set { myproperty = value; }
      }
    }
    
  2. Добавлен атрибут в свойство объекта следующим образом:

    [HelpPrompt("ProjectDescription")]
    [Required(ErrorMessageResourceName = "ProjectDescriptionRequired", ErrorMessageResourceType = typeof(EntityValidationMessages))]
    [StringLength(50, ErrorMessageResourceName = "ProjectDescriptionTooLong", ErrorMessageResourceType = typeof(EntityValidationMessages))]
    public string ProjectDescription { get; set; }
    
  3. Добавлен метод расширения для сущностей следующим образом:

    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. Добавлен HtmlHelper (простой) следующим образом:

    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. И, наконец, использовал следующую разметку в представлении:

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

Это делает работу, хотя и требует доработки. ;)

1 голос
/ 28 сентября 2011

Я знаю, что это старая версия, но недавно я столкнулся с этой проблемой в проекте ASP.NET MVC3 и реализовал решение.

1. Создайте пользовательский атрибут для хранения текста справки

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

2. Создайте метод расширения HtmlHelper для получения значения атрибута

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. Аннотируйте свойство модели с помощью атрибута HelpText

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

4. Просто используйте новый метод расширения HtmlHelper с вашим видом

<div class="editor-help">
    <%: Html.HelpTextFor(model => model.Level) %>
</div>
1 голос
/ 01 октября 2009

Я не думаю, что есть способ сделать это прямо из коробки.

Что вы могли бы сделать, так это создать общий класс «модель-значение», который инкапсулировал бы эту информацию в нем, таким образом, сохраняя ваше строго типизированное представление. а именно:

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

Затем можно создать классы модели, чтобы они содержали свойства типа ModelValue.

Ваш код выше будет выглядеть примерно так:

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

Недостатком этого является то, что я не думаю, что mvc выполнит автоматическое связывание для вас, поэтому вам придется выполнять все отображения в представлении самостоятельно, как в этом примере, но также и в Post, который вы будете делать должны сделать ручную привязку, если вы еще этого не сделали. Вы, вероятно, также создадите все свои свойства ModelValue в конструкторе модели и извлечете все значения заголовков из того места, где они хранятся, потому что вы не будете связывать их в Post (я думаю об ошибках проверки, приводящих к тому, что форма будет перерисована).

Если бы вы были очень заинтересованы, вы бы добавили атрибуты в свойства вашей модели, а затем каким-то образом проанализировали их при рендеринге страницы, но я понятия не имею, с чего начать, если вы хотите пойти по этому пути.

1 голос
/ 01 октября 2009

Обновление:

Вы можете просто создать новое свойство класса для каждого объекта с именем «Заголовок» или «Подсказка» и добавить к ним соответствующее строковое значение. Затем получите это свойство с MyObject.Title


Интересный вопрос. Я хотел бы увидеть ответ на этот вопрос с помощью атрибутов, но вот два способа, о которых я могу подумать:

Добавить метод расширения для ваших объектов Это потребовало бы много повторяющегося кода.

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

Метод расширения Html Helper

Вы бы сохраняли заголовки объектов в этом вспомогательном методе.

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;
     }
}

Чтобы вызвать этот метод:

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

Или в вашем примере:

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

Я предпочитаю второй метод, потому что у вас есть место для хранения всех заголовков, и вам нужно будет писать меньше кода.

Однако я думаю, что добавление атрибута в класс и создание средств для получения этого атрибута будет работать немного лучше.

...