IMetadataAware.OnMetadataCreated is never called

I created an attribute class to attach metadata to properties, so I can display tooltips for form input fields.

HelpAttribute implements 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 

I use this metadata in my extension method:

 <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 

Therefore, I can call Html.HelpFor for any of my model properties, and if it has the appropriate metadata, I show a help icon that shows a tooltip on click (js).

Everything works fine as long as the HelpAttribute is defined in the same assembly as the classes that I decorate with their properties. Today I had to move HelpAttribute to a separate dll (another namespace), so I did this, I referenced the project and expected it to work. I do not get compiler errors, the application works fine, but help icons do not appear on it. I debugged the code, and I see that the HelpAttribute constructor is HelpAttribute called for different properties with the correct text, but OnMetadataCreated never being called. Does anyone have an idea why this is so and how to fix it?

+6
source share
3 answers

I will answer my question again. Obviously, putting things on SO helps me structure the problem in my head. When I moved HelpAttribute to a separate class library, I had to refer to the System.Web.Mvc interface for IMetadataAware . I use .NET 4.0 , and I automatically reference MVC4, which I installed some time ago for testing. I had no errors, it just didn't work. When I changed System.Web.Mvc to ver. 3.0 everything works smoothly.

+2
source

Another reason this cannot be caused is to have the wrong namespace. So

 using System.Web.ModelBinding; 

will compile and not hit, but you have to use

 using System.Web.Mvc; 
+13
source
  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]}) } } 
-2
source

Source: https://habr.com/ru/post/910356/


All Articles