I have a custom implementation of a block that works much like Html.BeginForm()
. The implementation is basically as follows:
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");
}
}
Then in my view I can do:
@using (new MyBlock(Html)) {
@: some content
}
To get:
BEGIN
some content
END
This all works fine. However, I run into trouble when using my block inside a "razor snippet", e. g. when passing some razor content to a function which takes a Func<object, HelperResult>
as an argument. For example, I have another HtmlHelper function defined as follows:
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
When I do the following, though, the inner content renders without the outer content:
@{
var content =Html.Content(
@<text>
@using (new MyBlock(Html)) {
@: some content 2
}
<text>
);
}
@content
I think the issue is that "Html" still refers to the HtmlHelper of the outer context, and thus BEGIN and END are sent to a different writer than "some content 2", however, I'm not sure that this is the case.
Does anyone know (1) what is going wrong and (2) how I can fix it?
Partial solution of your problem is to invoke WriteTo method of HelperResult. You can change Content method to something like this:
public static void Content(this HtmlHelper @this, Func<object, HelperResult> razor)
{
razor(null).WriteTo(@this.ViewContext.Writer);
}
and then use it that way:
@{ Html.Content(
@<text>
@using (new MyBlock(Html)) {
@: some content 2
}
</text>
);
}
EDIT
If you would like to return value as IHtmlString or any other string you can do this:
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With