2012-03-09 118 views
6

我創建了屬性類來將元數據附加到屬性,因此我可以顯示錶單輸入字段的工具提示。IMetadataAware.OnMetadataCreated永遠不會調用

HelpAttribute實現IMetadataAware

Public Class HelpAttribute 
    Inherits Attribute 
    Implements System.Web.Mvc.IMetadataAware 

    Public Sub New(text As String) 
     _text = text 
    End Sub 

    Private _text As String 
    Public ReadOnly Property Text As String 
     Get 
      Return _text 
     End Get 
    End Property 

    Public Sub OnMetadataCreated(metadata As System.Web.Mvc.ModelMetadata) Implements System.Web.Mvc.IMetadataAware.OnMetadataCreated 
     metadata.AdditionalValues.Add("HelpText", _text) 
    End Sub 
End Class 

我利用這個元數據在我的擴展方法:

<Extension()> 
Public Function HelpFor(Of TModel, TProperty)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty))) As MvcHtmlString 
    Dim metaData = ModelMetadata.FromLambdaExpression(Of TModel, TProperty)(expression, htmlHelper.ViewData) 

    If metaData.AdditionalValues.ContainsKey("HelpText") Then 
     Dim helpText = metaData.AdditionalValues("HelpText") 
     Return MvcHtmlString.Create(String.Format("<span class=""help""></span><div class=""tooltip"" style=""display: none""><div class=""border-top""></div><div class=""close""><a href=""#"">close</a></div><br class=""clear""><div class=""content"">{1}</div></div>", htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(metaData.PropertyName), helpText, metaData.DisplayName)) 
    End If 

    Return MvcHtmlString.Create(String.Format("<span class=""no_help""></span>", htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(metaData.PropertyName), metaData.DisplayName)) 
End Function 

所以我可以打電話Html.HelpFor任何我的模型的屬性,如果有合適的元數據我展示點擊(js)顯示工具提示的幫助圖標。

只要HelpAttribute在與我裝飾其屬性的類相同的程序集中定義,這一切都可以正常工作。今天我必須將HelpAttribute移動到一個單獨的dll(不同的命名空間),所以我這樣做了,我引用了該項目,並期望它可以工作。我沒有收到任何編譯器錯誤,該應用程序工作正常,但它不顯示幫助圖標。我調試了代碼,發現HelpAttribute的構造函數被調用了不同的屬性和正確的文本,但OnMetadataCreated永遠不會被調用。有沒有人有一個想法,爲什麼這是如何解決它?

回答

2

我再次自己回答我的問題。顯然在SO上發佈內容有助於我在頭腦中構建問題。當我將HelpAttribute移動到一個單獨的類庫時,我不得不參考System.Web.MvcIMetadataAware接口。我使用.NET 4.0,並且我自動引用了前段時間爲安裝測試目的而安裝的MVC4。它沒有給我任何錯誤,它只是沒有工作。當我將System.web.Mvc更改爲版本。 3.0一切正常順利。

-2
using System; 
    using System.Collections.Generic; 
    using System.Globalization; 
    using System.Web; 
    using System.Web.Mvc; 

    namespace ColorPickerAttributeExample.Attributes 
    { 
     [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
     public sealed class ColorPickerAttribute : Attribute, IMetadataAware 
     { 
      private const string Template = 
       "$('#{0}').ColorPicker({{onSubmit: function(hsb, hex, rgb, el) {{" + 
       "var self = $(el); self.val(hex);self.ColorPickerHide();}}, onBeforeShow: function() " + 
       "{{$(this).ColorPickerSetColor(this.value);}}}}).bind('keyup', function(){{ $(this).ColorPickerSetColor(this.value); }});"; 

      public const string ColorPicker = "_ColorPicker"; 

      private int _count; 

      // if using IoC container, you could inject this into the attribute 
      internal HttpContextBase Context 
      { 
       get { return new HttpContextWrapper(HttpContext.Current); } 
      } 

      public string Id 
      { 
       get { return "jquery-colorpicker-" + _count; } 
      } 

      #region IMetadataAware Members 

      public void OnMetadataCreated(ModelMetadata metadata) 
      { 
       IList<string> list = Context.Items["Scripts"] as IList<string> ?? new List<string>(); 
       _count = list.Count; 

       metadata.TemplateHint = ColorPicker; 
       metadata.AdditionalValues[ColorPicker] = Id; 

       list.Add(string.Format(CultureInfo.InvariantCulture, Template, Id)); 

       Context.Items["Scripts"] = list; 
      } 

      #endregion 
     } 
    } 



    using ColorPickerAttributeExample.Attributes; 
    using System; 

    namespace ColorPickerAttributeExample.Models 
    { 
     public class HomeModel 
     { 
      [ColorPicker] 
      public string ColorPicker { get; set; } 
      [ColorPicker] 
      public DateTime ColorPicker2 { get; set; } 
     } 
    } 


@model dynamic 

@{ 
    var picker = ViewData.GetModelAttribute<ColorPickerAttribute>(); 
    if (picker != null) 
    { 
     @Html.LabelForModel() 
     @Html.TextBoxFor(m => m, new {id = ViewData.ModelMetadata.AdditionalValues[ColorPickerAttribute.ColorPicker]}) 
    } 
} 
+0

這裏發佈的代碼不屬於提出的問題,它只是沒有考慮上下文中的樣板屬性OP的問題。即使代碼是有用的 - 它不應該被毫不客氣地拋棄,沒有解釋它的作用以及它如何回答原始問題。 – RobD 2014-03-28 17:50:46

13

這可能不會被調用的另一個原因是如果你有錯誤的名稱空間引用。所以

using System.Web.ModelBinding; 

將編譯並不會被撞到,但你應該使用

using System.Web.Mvc; 
+0

謝謝!我不想想象要花多長時間才能弄清楚這一點。 – Gerino 2017-10-18 21:39:11

相關問題