简体   繁体   English

MVC:在自定义HTML帮助器中读取内容

[英]MVC: Reading the contents inside a custom HTML helper

I'm trying to build an HTML helper which conditionally modifies its content. 我正在尝试构建一个HTML助手,该助手有条件地修改其内容。 The reason is so that I can move the contents to another part of the page (in the context of master page and child views) or remove them completely given some circumstances. 原因是,在某些情况下,我可以将内容移至页面的另一部分(在母版页视图和子视图的上下文中)或将其完全删除。

As an example, I might have some JavaScript that I either wish to move elsewhere (bear in mind that section objects only work if the view directly references the page which hosts that named section) or perhaps if I wish to qualify some JavaScript calls with a module namespace. 举例来说,我可能有一些我想移到其他地方的JavaScript(请记住,只有在视图直接引用承载该命名部分的页面的情况下, section对象才起作用),或者如果我希望用模块名称空间。

I have no problem in building the IDisposable which forms the main part of the HTML helper, and I know how to write contents into the page's output, but I can't figure out how to read in the contents. 构建IDisposable构成HTML帮助程序的主要部分时,我没有问题,而且我知道如何内容写入页面的输出中,但是我不知道如何读取内容。

For example, if I have this on my Razor view: 例如,如果我在Razor视图上有此设置:

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

And then have 然后有

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

What do I need in that static helper method to retrieve the <div>hello world</div> contents? 在该静态助手方法中,需要什么来检索<div>hello world</div>内容?

You can call this code on initialization of helper: 您可以在辅助程序初始化时调用以下代码:

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

to get current string that is in your context. 获取当前上下文中的字符串。

And then compare result of same code on disposing this control to get content that is inside your helper. 然后比较相同代码在配置此控件上的结果,以获取帮助程序中的内容。

This seems like a strange approach that may have an alternative solution that is more effective. 这似乎是一种奇怪的方法,可能会有更有效的替代解决方案。 One observation: everything inside of your using is static (hard coded) in the view. 一项观察:在视图中,您使用的所有内容都是静态的(硬编码)。 This means that there must be other external variables that affect what gets rendered since what is in the view is not dynamic. 这意味着必须有其他外部变量影响呈现的内容,因为视图中的内容不是动态的。 <div>My div</div> will never change, so what type of logic could be performed on it that wouldn't always result in the same thing? <div>My div</div>永远不会改变,因此可以对它执行哪种逻辑,而这种逻辑并不总是会导致同一件事?

I'll cover one reason why (there may be more), then propose an alternate solution. 我将介绍一个原因(可能还有更多),然后提出另一种解决方案。

Why? 为什么?

Consider this example: 考虑以下示例:

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

In this case, @Model is a dynamic value that isn't known until runtime and serves only as a place holder for some server side value to be replaced by actual content once the whole MVC pipeline is invoked (which will happen after you invoke your helper). 在这种情况下,@ Model是一个动态值,直到运行时才知道,并且仅用作占位符,以便在调用整个MVC管道后将某些服务器端值替换为实际内容(在调用您的帮手)。 What should the helper do in this case? 在这种情况下,助手应该做什么? It has no way to identify what @Model (or what MyCustomContent) is. 它无法识别@Model(或MyCustomContent)是什么。 Additionally, conditional logic and/or looping inside of the using would also pose a challenge in this case. 另外,在这种情况下,使用中的条件逻辑和/或循环也会带来挑战。

Perhaps more problematic (for similar reasons), would be something like this: 也许有更多问题(出于类似原因)如下所示:

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

In this case, what we want is for the inner using to execute first, render a string output, then for the outer using to execute, using the output rendered by the inner using, but this is not how the code will execute. 在这种情况下,我们想要的是内部用户首先执行,呈现字符串输出,然后使用内部用户所呈现的输出,让外部用户执行,但这不是代码将如何执行。

An Alternative: 替代:

Instead, consider having the contents you want to conditionally render be in a separate partial view: 相反,请考虑将要有条件渲染的内容放在单独的局部视图中:

//MyPartialView.cshtml //MyPartialView.cshtml

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

Then you could say in your main view: 然后,您可以在主视图中说:

@Html.MyHtmlHelper("MyPartialView", Model)

In your extension method: 在您的扩展方法中:

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);
}

A second alternative: 第二种选择:

If you wanted, you could use properties of a model or context to determine what to render where, and when. 如果需要,可以使用模型或上下文的属性来确定在何时何地呈现什么。

If you had a view model: 如果您有视图模型:

public class ConditionalRenderingViewModel {

    public bool ShouldRenderJavascript {get; set;}

}

Then, in your view: 然后,在您看来:

@Html.MyHtmlHelper(Model)

Then, in your Html helper 然后,在您的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("");
    }
}

This gives you the ability to control the output without parsing text or relying on hard-coded view markup. 这使您能够控制输出,而无需解析文本或依靠硬编码的视图标记。

You can see some additional strategies here: http://www.codemag.com/Article/1312081 您可以在此处查看一些其他策略: http : //www.codemag.com/Article/1312081

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM