Razor:自定义BeginForm()类Razor一次性块在某些情况下不起作用
本文关键字:Razor 不起作用 情况下 自定义 BeginForm 一次性 | 更新日期: 2023-09-27 17:50:32
我有一个自定义的块实现,它的工作原理很像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被发送到不同的作者而不是"一些内容2",然而,我不确定这是情况。
有谁知道(1)什么是错的(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;
}
}
}
这个问题也困扰了我一段时间。这是一个剃刀错误,由于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