我正在使用示例found here来允许从标记帮助器中呈现部分视图。我要在这里要做的是能够像这样定义一个标记助手:
<mydateinput for="@Model.StartDate" />
在标记帮助器的c#代码中,我将定义“ for”属性,据我所知,这需要定义为“ ModelExpression”。
public class MyDateInputTagHelper : TagHelper
{
public ModelExpression For { get; set; }
...
}
使用this article中前面提到的代码,我正在渲染部分视图,并简单地将标记帮助器的类作为部分视图的模型传递。
public override void Process(TagHelperContext context, TagHelperOutput output)
{
base.Process(context, output);
((IViewContextAware)HtmlHelper).Contextualize(ViewContext);
output.Content.SetHtmlContent(HtmlHelper.Partial("~/Views/Partials/TagHelpers/MyDateInput.cshtml", this));
}
最后,我的局部视图定义如下:
<input asp-for="For" />
我遇到的问题是我无法使模型表达式“ For”正确传递到局部视图中。当我查看html源代码时,我只是在输入的id和name属性中实际看到名称“ For”。另外,在我的剃刀页面模型中设置的值也无法正确显示。
我想发生的是,将以这样一种方式呈现html:在发布页面时,将使用在标签helper / partial view下选择的值填充到我的剃刀页面的模型。具体来说,它将位于“ StartDate”(在我的示例中)周围,而不是属性“ For”。
有人知道我做错了什么吗?在此示例中可以更改哪些内容,以正确地将ModelExpression传递给局部视图?
答案 0 :(得分:1)
不可能直接使用InputTagHelper
来做到这一点。有关更多信息,请参见Razor/issues #926和a similar question on SO。
Walkaournd
但是,作为一种解决方法,您可以使用自定义的HtmlHelper<TModel>
(就像@Html
一样)。您的局部视图可能如下所示:
@model App.TagHelpers.PartialVM
@{
var PartialHtml = Model.HtmlHelper;
}
@PartialHtml.Label(Model.NewFor.Name,Model.NewFor.Name)
@PartialHtml.TextBox(Model.NewFor.Name, Model.NewModel)
即,使用@Html.Label()
和@Html.TextBot
而不是<label>
和<input>
。
PartialVM
是一个简单的类,其中包含有关模型的元信息:
public class PartialVM
{
public PartialVM(ModelExpression originalFor, IHtmlHelper htmlHelper)
{
var originalExplorer = originalFor.ModelExplorer;
OriginalFor = originalFor;
OriginalExplorer = originalExplorer;
NewModel = originalExplorer.Model;
NewModelExplorer = originalExplorer.GetExplorerForModel(NewModel);
NewFor = new ModelExpression(OriginalFor.Name, NewModelExplorer);
this.HtmlHelper = htmlHelper;
}
public IHtmlHelper HtmlHelper { get; set; }
public ModelExpression OriginalFor { get; set; }
public ModelExplorer OriginalExplorer { get; set; }
public ModelExpression NewFor { get; set; }
public ModelExplorer NewModelExplorer { get; set; }
public Object NewModel { get; set; }
}
请注意,IHtmlHelper
实际上是 IHtmlHelper<TSomeDynamicModel>
而不是普通的IHtmlHelper
。
最后,如下更改您的TagHelper
:
[HtmlTargetElement("my-custom-input")]
public class MyCustomInputTagHelper : TagHelper
{
private readonly IServiceProvider _sp;
[ViewContext]
public ViewContext ViewContext { set; get; }
public ModelExpression For { get; set; }
public MyCustomInputTagHelper(IServiceProvider sp)
{
this._sp = sp;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
base.Process(context, output);
var originExplorer = For.ModelExplorer;
var newModel = originExplorer.Model;
var newExplorer = originExplorer.GetExplorerForModel(newModel);
var newFor = new ModelExpression(For.Name, newExplorer);
var ModelType = originExplorer.Container.Model.GetType();
var htmlHelperType = typeof(IHtmlHelper<>).MakeGenericType(ModelType);
var htmlHelper = this._sp.GetService(htmlHelperType) as IHtmlHelper; // get the actual IHtmlHelper<TModel>
(htmlHelper as IViewContextAware).Contextualize(ViewContext);
var vm = new PartialVM(For, htmlHelper);
var writer = new StringWriter();
var content = await htmlHelper.PartialAsync("~/Views/Partials/TagHelpers/MyDateInput.cshtml", vm);
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
output.Content.SetHtmlContent(content);
}
}
现在,您可以为asp-for
的{{1}}属性传递任何For
表达式字符串,并且应该可以正常工作。
测试用例:
假设我们有一个Dto模型:
TagHelper
您可以通过以下方式呈现它:
public class XModel {
public int Id { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string ActiveStatus{ get; set; }
}
以下是渲染时的屏幕截图: