IMetadataAware.OnMetadataCreated никогда не вызывается - PullRequest
6 голосов
/ 09 марта 2012

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

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 никогда не вызывается.У кого-нибудь есть идея, почему это так и как это исправить?

Ответы [ 3 ]

14 голосов
/ 02 апреля 2015

Другая причина, по которой это не может быть вызвано, - неправильная ссылка на пространство имен. Так

using System.Web.ModelBinding;

будет компилироваться и не попадать, но вы должны использовать

using System.Web.Mvc;
2 голосов
/ 09 марта 2012

Еще раз сам отвечу на свой вопрос.Очевидно, что размещение сообщений на SO помогает мне структурировать проблему в моей голове.Когда я переместил HelpAttribute в отдельную библиотеку классов, мне пришлось ссылаться на System.Web.Mvc для интерфейса IMetadataAware.Я использую .NET 4.0 и автоматически ссылаюсь на MVC4, который я установил некоторое время назад для целей тестирования.Это не получило никаких ошибок, просто не сработало.Когда я изменил System.web.Mvc на вер.3.0 все работает плавно.

0 голосов
/ 20 января 2014
    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]})
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...