MVC:读取自定义 HTML 帮助程序中的内容

本文关键字:帮助程序 HTML 读取 自定义 MVC | 更新日期: 2023-09-27 18:25:53

我正在尝试构建一个有条件地修改其内容的HTML助手。原因是我可以将内容移动到页面的另一部分(在母版页和子视图的上下文中(或在某些情况下完全删除它们。

例如,我可能有一些 JavaScript 我希望移动到其他地方(请记住,section对象仅在视图直接引用托管该命名部分的页面时才有效(,或者如果我希望使用模块命名空间限定一些 JavaScript 调用。

我在构建构成 HTML 助手主要部分的IDisposable方面没有问题,并且我知道如何将内容写入页面的输出,但我无法弄清楚如何阅读内容。

例如,如果我的 Razor 视图上有这个:

@using (Html.MyHtmlHelper())
{
    <div>hello world</div>
}

然后有

private static IDisposable MyHtmlHelper(this HtmlHelper htmlHelper)
{
    // ...
}

在该静态帮助程序方法中,我需要什么来检索<div>hello world</div>内容?

MVC:读取自定义 HTML 帮助程序中的内容

您可以在初始化帮助程序时调用此代码:

var strContents = new HtmlTextWriter(htmlHelper.ViewContext.Writer).InnerWriter.ToString();

获取上下文中的当前字符串。

然后在释放此控件时比较相同代码的结果,以获取帮助程序内的内容。

这似乎是一种奇怪的方法,可能有更有效的替代解决方案。一个观察:使用中的所有内容在视图中都是静态的(硬编码(。 这意味着必须有其他外部变量影响渲染的内容,因为视图中的内容不是动态的。 <div>My div</div>永远不会改变,那么可以对它执行什么类型的逻辑,并不总是导致同样的事情?

我将介绍一个原因(可能还有更多(,然后提出另一种解决方案。

为什么?

请考虑以下示例:

@using(Html.MyHtmlHelper()) {
    <div>Normal Text, no problem in theory</div>
    <span>@Model.MyCustomContent</span>
}

在这种情况下,@Model 是一个动态值,直到运行时才知道,并且仅用作某些服务器端值的占位符,以便在调用整个 MVC 管道后替换为实际内容(这将在调用帮助程序后发生(。 在这种情况下,帮助程序应该怎么做? 它无法识别@Model(或MyCustomContent(是什么。 此外,在这种情况下,使用中的条件逻辑和/或循环也会带来挑战。

也许更成问题的(出于类似的原因(,会是这样的:

@using(Html.MyHtmlHelper()) {
    <div>Normal Text, no problem in theory</div>
    <span>@Model.MyCustomContent</span>
    @using(Html.MyHtmlHelper()) {
        <div>More nested custom stuff</div>
    }
}

在这种情况下,我们想要的是让内部 using 首先执行,渲染一个字符串输出,然后让外部 using 执行,使用内部 using 渲染的输出,但这不是代码的执行方式。

另一种选择:

相反,请考虑将要有条件呈现的内容放在单独的分部视图中:

/

/MyPartialView.cshtml

<div>Hello World</div>
@Model.CustomContent
<div>Dynamic Switcheroo</div>

然后你可以在你的主视图中说:

@Html.MyHtmlHelper("MyPartialView", Model)

在扩展方法中:

private static HtmlString MyHtmlHelper(this HtmlHelper htmlHelper, string viewName, object model)
{
    string output = htmlHelper.Partial(viewName, model).ToHtmlString();
    //TODO: Conditional string parsing based on output
    string formattedOutput = output.SomeOperation();
    return new HtmlString(formattedOutput);
}

第二种选择:

如果需要,可以使用模型或上下文的属性来确定在何处以及何时呈现的内容。

如果您有视图模型:

public class ConditionalRenderingViewModel {
    public bool ShouldRenderJavascript {get; set;}
}

然后,在您看来:

@Html.MyHtmlHelper(Model)

然后,在您的 HTML 帮助程序中

public static HtmlString MyHtmlHelper(ConditionalRenderingViewModel model) {
    if(model.ShouldRenderJavascript) {
        return new HtmlString("<script type='text/javascript' src='customjs.js'></script>");
    } else {
        return new HtmlString("");
    }
}

这使您能够控制输出,而无需分析文本或依赖硬编码的视图标记。

您可以在此处查看一些其他策略:http://www.codemag.com/Article/1312081