9

のように機能するブロックのカスタム実装がありますHtml.BeginForm()。実装は基本的に次のとおりです。

public class MyBlock : IDisposable {
    private readonly HtmlHelper _html;

    public MyBlock(HtmlHelper hml) {
        this._html.ViewContext.Writer.WriteLine("BEGIN");
    }

    public void Dispose() {
        this._html.ViewContext.Writer.WriteLine("END");
    }
}

次に、私の見解では、次のことができます。

@using (new MyBlock(Html)) {
    @: some content
}

取得するため:

BEGIN
some content
END

これはすべてうまくいきます。ただし、「かみそりのスニペット」内でブロックを使用すると、たとえば、かみそりのコンテンツを引数として取る関数に渡すときに問題が発生しFunc<object, HelperResult>ます。たとえば、次のように定義された別の HtmlHelper 関数があります。

public static IHtmlString Content(this HtmlHelper @this, Func<object, HelperResult> razor) {
    return razor(null);
}

@* use in a view as: *@
@{
    var razorContent = Html.Content(@<div>Some razor content</div>);
}
@razorContent

ただし、次のようにすると、内側のコンテンツは外側のコンテンツなしでレンダリングされます。

@{ 
    var content =Html.Content(
        @<text>
            @using (new MyBlock(Html)) {
                @: some content 2
            }
        <text>
    );
}
@content

問題は、「Html」がまだ外部コンテキストの HtmlHelper を参照しているため、BEGIN と END が「some content 2」とは異なるライターに送信されることだと思いますが、これが事実かどうかはわかりません。

(1)何がうまくいかないのか、(2)どうすれば修正できるのか、誰でも知っていますか?

4

2 に答える 2

2

問題の部分的な解決策は、HelperResult の WriteTo メソッドを呼び出すことです。Content メソッドを次のように変更できます。

public static void Content(this HtmlHelper @this, Func<object, HelperResult> razor)
{
    razor(null).WriteTo(@this.ViewContext.Writer);
}

そして、そのように使用します:

@{ Html.Content(
        @<text>
            @using (new MyBlock(Html)) {
                @: some content 2
            }
        </text>
    );
}

編集

値を IHtmlString またはその他の文字列として返したい場合は、次のようにすることができます。

public static IHtmlString Content(this HtmlHelper @this, Func<object, HelperResult> razor)
{
    using (MemoryStream ms = new MemoryStream())
    using (TextWriter tw = new StreamWriter(ms))
    {
        Delegate @delegate = (Delegate)razor;
        WebViewPage target = (WebViewPage)@delegate.Target;
        TextWriter tmp = target.Html.ViewContext.Writer;
        try
        {
            target.Html.ViewContext.Writer = tw;
            razor(null).WriteTo(tw);
            tw.Flush();
            ms.Seek(0, SeekOrigin.Begin);
            TextReader tr = new StreamReader(ms);

            return MvcHtmlString.Create(tr.ReadToEnd());
        }
        finally
        {
            target.Html.ViewContext.Writer = tmp;
        }
    }
}
于 2013-01-10T19:34:31.990 に答える
0

これもしばらくの間私を悩ませてきました。これは、MyBlock と HtmlHelper が異なるライターを使用しているため、かみそりのバグです。合理的な回避策は、HtlmHelper の __razor_template_writer を MyBlock に渡すことです。(うまくいけば、これは vnext で修正されるでしょう)

public class MyBlock : IDisposable {
    private readonly TextWriter _writer;

    public MyBlock(TextWriter writer) {
        _writer = writer;
        _writer.WriteLine("BEGIN");
    }

    public void Dispose() {
        _writer.WriteLine("END");
    }
}

@{ 
    var content =Html.Content(
        @<text>
            @using (new MyBlock(__razor_template_writer)) {
                @: some content 2
            }
        <text>
    );
}
@content
于 2014-09-01T19:43:25.297 に答える