Я пытаюсь создать пользовательский ModelMetadataProvider
, чтобы предоставить ненавязчивые атрибуты виджета автозаполнения пользовательского интерфейса JQuery.ModelMetadata TemplateHint always null
У меня есть пользовательский атрибут, который выглядит следующим образом:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class AutocompleteAttribute : Attribute, IMetadataAware
{
public void OnMetadataCreated(ModelMetadata metadata)
{
metadata.TemplateHint = "Autocomplete";
}
}
и шаблон редактора, который выглядит следующим образом:
@{
var attributes = new RouteValueDictionary
{
{"class", "text-box single-line"},
{"autocomplete", "off"},
{"data-autocomplete-url", "UrlPlaceholder" },
};
}
@Html.TextBox("", ViewContext.ViewData.TemplateInfo.FormattedModelValue, attributes)
У меня есть ViewModel со свойством типа string
, которая включает AutocompleteAttribute
:
public class MyViewModel
{
[Autocomplete]
public string MyProperty { get; set; }
}
Когда я использую is viewModel в моем представлении Я проверяю сгенерированный html, и я получаю тег <input>
, который имеет такой атрибут: data-autocomplete-url="UrlPlaceholder"
.
То, что я хочу делать дальше, чтобы иметь возможность указать URL, на мой взгляд, который использует мои ViewModel как это:
@model MyViewModel
@{ ViewBag.Title = "Create item"; }
@Html.AutoCompleteUrlFor(p => p.MyProperty, UrlHelper.GenerateUrl(null, "Autocomplete", "Home", null, Html.RouteCollection, Html.ViewContext.RequestContext, true))
// Other stuff here...
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Мой AutoCompleteForUrl
помощник просто сохраняет сгенерированный URL в словаре, используя свойство имя в качестве ключа.
Далее Я создал обычай ModelMetadataProvider
и зарегистрировал его в global.asax, используя эту строку кода ModelMetadataProviders.Current = new CustomModelMetadataProvider();
.
Что я хочу сделать, это вставить URL-адрес, который будет использоваться виджетами автозаполнения JQuery UI, в словарь metadata.AdditionalValues
, который будет использоваться шаблоном редактора Autocomplete.
Моего заказ ModelMetadataProvider
выглядит следующим образом:
public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<System.Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
if (metadata.TemplateHint == "Autocomplete")
{
string url;
if(htmlHelpers.AutocompleteUrls.TryGetValue(metadata.propertyName, out url)
{
metadata.AdditionalValues["AutocompleteUrl"] = url;
}
}
return metadata;
}
}
и мой обновленный шаблон редактора выглядит следующим образом:
@{
object url;
if (!ViewContext.ViewData.ModelMetadata.TryGetValue("AutocompleteUrl", out url))
{
url = "";
}
var attributes = new RouteValueDictionary
{
{"class", "text-box single-line"},
{"autocomplete", "off"},
{"data-autocomplete-url", (string)url },
};
}
@Html.TextBox("", ViewContext.ViewData.TemplateInfo.FormattedModelValue, attributes)
Проблема есть, TemplateHint
свойства никогда не равно «подсказки» в моей пользовательской модели поставщик метаданных, поэтому моя логика генерации URL-адреса никогда не вызывается. Я бы подумал, что в этот момент свойство TemplateHint
будет установлено так, как я назвал базовую реализацию CreateMetadata
DataAnnotationsModelMetadataProvider
.
Вот что я могу подтвердить:
CustomModelMetadataProvider
правильно зарегистрирован, поскольку он содержит другой код, который вызывался.- Правильный шаблон редактора получает выбранный HTML-код, содержащий атрибут
"data-autocomplete-url"
. - Если я поставил точку останова в шаблоне автозаполнения, Visual Studio отправится к отладчику.
Так может ли кто-нибудь пролить свет на это для меня, пожалуйста? Что я не понимаю о системе ModelMetadataProvider
?