如何在MVC中向业务对象添加帮助提示属性并在视图中显示

发布于 2024-08-06 19:26:06 字数 311 浏览 10 评论 0原文

如何在 ASP.Net MVC 应用程序中针对我的业务对象提供某种形式的属性,以便我可以在视图中选取帮助文本并将它们显示为弹出悬停帮助文本,如下所示:

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

我希望能够从我的 ViewModel 获取“标题”值,该视图模型将从业务对象的属性中获取文本。

总之,如何在我的业务对象上应用帮助文本属性/元数据?

How can I provide some form of Attribute against my Business Objects in my ASP.Net MVC application so that I can pick up the help texts in the View and have them appear as pop-up hover help texts like this:

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

I want to be able to get the 'title' value from my ViewModel which will have picked up the text from an attribute on the Business Object.

In summary, how can I apply help text attributes / metadata on my Business Objects?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

酷到爆炸 2024-08-13 19:26:06

我是这样做的:

  1. 创建新属性如下:

    公共类HelpPromptAttribute:属性
    {
      公共HelpPromptAttribute(字符串文本)
      {
          我的属性=文本; 
      }
      受保护的字符串 myproperty;
    
      公共字符串 HelpTextKey
      {
          得到{返回我的财产; }
          设置 { myproperty = 值; }
      }
    }
    
  2. 向实体属性添加了属性,如下所示:

    [HelpPrompt("项目描述")]
    [必需(ErrorMessageResourceName =“ProjectDescriptionRequired”,ErrorMessageResourceType = typeof(EntityValidationMessages))]
    [StringLength(50,ErrorMessageResourceName = "ProjectDescriptionTooLong",ErrorMessageResourceType = typeof(EntityValidationMessages))]
    公共字符串项目描述{获取;放; }
    
  3. 向实体添加扩展方法,如下:

    公共静态类EntityBOExtensions
    {
      公共静态字符串PropertyHelp(此对象objectBO,字符串PropertyName)
      {
          类型 type = objectBO.GetType();
    
    
          foreach (PropertyInfo pInfo in type.GetProperties())
          {
              if (string.Compare(pInfo.Name, PropertyName) == 0)
              {
                  foreach(Attribute.GetCustomAttributes(pInfo) 中的属性 attr)
                  {
                      if (attr.GetType() == typeof(HelpPromptAttribute))
                      {
                          字符串键 = ((HelpPromptAttribute)attr).HelpTextKey;
                          if (!string.IsNullOrEmpty(key))
                              返回 EntityBOHelp.ResourceManager.GetString(key);
                      }
                  }
              }
          }
          返回空值;
      }
    }
    
  4. 添加了一个 HtmlHelper(简单),如下:

    public static string LocalizedTextBoxWithHelp(此 HtmlHelper 帮助程序,字符串名称,对象值,字符串帮助文本)
    {
        string textbox = helper.TextBox(名称, 值, new { helpprompt = helptext });
        返回文本框;
    }
    
  5. 最后在视图中使用了以下标记:

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

尽管需要改进,但它完成了工作。 ;)

Here is how I did it:

  1. Created new Attribute as follows:

    public class HelpPromptAttribute : Attribute
    {
      public HelpPromptAttribute(string text)
      {
          myproperty = text; 
      }
      protected string myproperty;
    
      public string HelpTextKey
      {
          get { return myproperty; }
          set { myproperty = value; }
      }
    }
    
  2. Added attribute to entity property as follows:

    [HelpPrompt("ProjectDescription")]
    [Required(ErrorMessageResourceName = "ProjectDescriptionRequired", ErrorMessageResourceType = typeof(EntityValidationMessages))]
    [StringLength(50, ErrorMessageResourceName = "ProjectDescriptionTooLong", ErrorMessageResourceType = typeof(EntityValidationMessages))]
    public string ProjectDescription { get; set; }
    
  3. Added Extension Method to Entities as follows:

    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. Added a HtmlHelper (simple) as follows:

    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. And finally used the folowing markup in the View:

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

This does the job although it needs refinement. ;)

前事休说 2024-08-13 19:26:06

我认为没有一种方法可以直接开箱即用。

不过,您可以做的是创建一个通用的“模型值”类,将这些信息封装在其中,从而保留您的强类型视图。即:

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 上重新绑定它们(我正在考虑这里的验证错误,导致表单被重新显示)。

如果您非常热衷,您可以在模型属性上添加属性,然后在渲染页面时以某种方式解析它们,但如果您想这样做,我不知道从哪里开始。

I don't think there is a way to do it straight out of the box.

What you could do though is create a generic "model value" class that encapsulated that information in it thus keeping your strongly typed view. ie:

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

You could then build up your model classes to contain properties of type ModelValue.

Your code above would then look something like:

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

The down side to doing this is that I don't think mvc is going to do automatic binding for you, so you'll have to do all the mapping in the view yourself like in this example but also on Post you will have to do manual binding if you aren't already.
You would probably also instantiate all your ModelValue properties in the constructor of the model and pull in all the title values from whever they are stored then because you wouldn't rebind them on Post (I am thinking about validation errors here causing the form to be redisplayed).

If you were super keen you would put attributes on your model properties and then somehow have them parsed when you render the page, but I have no idea where you would start if you wanted to go this way.

明媚殇 2024-08-13 19:26:06

更新:

您可以为每个名为“Title”或“Hint”的对象创建一个新的类属性,并向它们添加适当的字符串值。然后使用 MyObject.Title 获取该属性


有趣的问题。我希望看到使用属性对此问题的答案,但我可以想到两种方法:

向对象添加扩展方法
这将需要大量重复代码。

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

Html Helper 扩展方法

您可以在此 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()) })%>

我更喜欢第二种方法,因为您有一个地方可以存储所有标题,并且需要编写更少的代码。

但是,我认为向类添加一个属性并创建一种获取该属性的方法会更好一些。

Update:

You could just create a new class property for each of your object named "Title" or "Hint" and add the appropriate string value to them. Then get that property with MyObject.Title


Interesting question. I would like to see an answer to this using attributes, but here are two methods I can think of:

Add an extension method to your objects
This would require alot of repetitive code.

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

Html Helper extension method

You would store the object titles in this helper method.

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

To call this method:

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

Or in your example:

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

I prefer the 2nd method because you have a place to store all the titles and you would need to write less code.

However, I think adding an attribute to the class and creating a means to get that attribute would work a bit better.

阳光的暖冬 2024-08-13 19:26:06

我知道这已经很旧了,但我最近在 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>

I know this is old, but I faced this problem recently with an ASP.NET MVC3 project and implemented a solution.

1. Create a custom attribute to store the help text

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

2. Create a HtmlHelper extension method to retrieve the attribute value

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. Annotate the model property with the HelpText attribute

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

4. Simply use the new HtmlHelper extension method with your view

<div class="editor-help">
    <%: Html.HelpTextFor(model => model.Level) %>
</div>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文