我正在尝试创建一个自定义ModelMetadataProvider
来为 JQuery UI 自动完成小部件提供不显眼的属性。
我有一个看起来像这样的自定义属性:
[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)
我有一个视图模型,其类型属性string
包括AutocompleteAttribute
以下内容:
public class MyViewModel
{
[Autocomplete]
public string MyProperty { get; set; }
}
当我在我的视图中使用这个 viewModel 时,我检查生成的 html 并且我得到一个<input>
具有如下属性的标签:data-autocomplete-url="UrlPlaceholder"
.
我接下来要做的是能够在我的视图中指定使用我的 viewModel 的 URL,如下所示:
@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();
。
我想要做的是将要由 JQuery UI 自动完成小部件使用的 URL 插入到要metadata.AdditionalValues
由自动完成编辑器模板使用的字典中。
我的自定义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
系统有什么误解?