C# 将ModelExpression从标记辅助对象传递到局部视图

C# 将ModelExpression从标记辅助对象传递到局部视图,c#,asp.net-core,asp.net-core-mvc,razor-pages,asp.net-core-tag-helpers,C#,Asp.net Core,Asp.net Core Mvc,Razor Pages,Asp.net Core Tag Helpers,我使用这个示例允许从标记辅助对象中渲染局部视图。我在这里要做的是能够像这样定义标记帮助器: <mydateinput for="@Model.StartDate" /> 使用前面提到的代码,我呈现一个局部视图,并简单地将标记帮助器的类作为局部视图的模型传递 public override void Process(TagHelperContext context, TagHelperOutput output) { base.Process(cont

我使用这个示例允许从标记辅助对象中渲染局部视图。我在这里要做的是能够像这样定义标记帮助器:

<mydateinput for="@Model.StartDate" />
使用前面提到的代码,我呈现一个局部视图,并简单地将标记帮助器的类作为局部视图的模型传递

    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”。另外,在我的razor页面模型中设置的值也没有正确显示

我想要实现的是,html将以这样一种方式呈现,即在发布页面时,我的razor页面的模型将填充在标记助手/局部视图下选择的值。它特别是在“StartDate”(在我的示例中)附近,而不是属性“For”


是否有人知道我做错了什么,以及在本例中我可以更改什么以正确地将ModelExpression传递到局部视图?

直接使用
InputAgHelper
无法做到这一点。有关更多信息,请参见和

解决方案

但是作为一种解决方法,您可以使用自定义
HtmlHelper
(就像
@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
而不是
&

这里的
PartialVM
是一个简单的类,它保存关于模型的元信息:

公共类PartialVM
{
公共PartialVM(ModelExpression原件,IHtmlHelper htmlHelper)
{
var originalExplorer=originalFor.ModelExplorer;
OriginalFor=OriginalFor;
originalexployer=originalexployer;
NewModel=originalExplorer.Model;
NewModelExplorer=originalExplorer.GetExplorerForModel(NewModel);
NewFor=newmodelexpression(OriginalFor.Name,newmodeleexplorer);
this.HtmlHelper=HtmlHelper;
}
公共IHtmlHelper HtmlHelper{get;set;}
{get;set;}的公共模型表达式源代码
公共ModelExplorer OriginalExplorer{get;set;}
{get;set;}的公共模型表达式
公共模型资源管理器NewModelExplorer{get;set;}
公共对象NewModel{get;set;}
}
注意
IHtmlHelper
实际上是一个
IHtmlHelper
而不是一个普通的
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);
        }
    }
可以按以下方式渲染它:

///操作方法如下所示:
///var模型=新的XModel{
///StartDate=日期时间。现在,
///EndDate=DateTime.Now.AddYears(1),
///ActiveStatus=“Active”,
///    };
///返回视图(模型);
@模型XModel
以下是渲染时的屏幕截图:


回答得真棒,感谢您抽出时间回答,并给我一个前进的选择!
    [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);
        }
    }
public class XModel {
    public int Id { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string ActiveStatus{ get; set; }
}