Capture Wrapped Content In BeginForm Style Disposable Html Helper
I am trying to write a BeginForm style html helper that uses IDisposable to wrap other code. I want the helper to only render the wrapped code if a certain condition is met (e.g. u
Solution 1:
Actually you can conditionally hide content with a BeginForm-like structure. It only involves messing with the internal StringBuilder a bit:
public class Restricted: IDisposable
{
public bool Allow { get; set; }
private StringBuilder _stringBuilderBackup;
private StringBuilder _stringBuilder;
private readonly HtmlHelper _htmlHelper;
/// <summary>
/// Initializes a new instance of the <see cref="Restricted"/> class.
/// </summary>
public Restricted(HtmlHelper htmlHelper, bool allow)
{
Allow = allow;
_htmlHelper = htmlHelper;
if(!allow) BackupCurrentContent();
}
private void BackupCurrentContent()
{
// make backup of current buffered content
_stringBuilder = ((StringWriter)_htmlHelper.ViewContext.Writer).GetStringBuilder();
_stringBuilderBackup = new StringBuilder().Append(_stringBuilder);
}
private void DenyContent()
{
// restore buffered content backup (destroying any buffered content since Restricted object initialization)
_stringBuilder.Length = 0;
_stringBuilder.Append(_stringBuilderBackup);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if(!Allow)
DenyContent();
}
}
Then you just need to make an HtmlHelper that makes an instance of the above object
public static class RestrictedHelper
{
public static Restricted RestrictedContent(this HtmlHelper htmlHelper, bool allow)
{
return new Restricted(htmlHelper, allow);
}
}
Usage is as follows:
@using (var restricted = Html.Restricted(true))
{
<p>This will show up</p>
}
@using (var restricted = Html.Restricted(false))
{
<p>This won't</p>
}
Advantages:
- Write custom logic to show/hide your content and pass it to the Restricted constructor.
- public properties in your Restricted object are accessible in the block of code in your view, so you can reuse calculated values there.
Tested with ASP.Net MVC 4
Solution 2:
You can't conditionally render the body contents of a helper method returning IDisposable
. It will always render. You could use this style of helpers when you want to wrap the body of the using
block with some custom markup such as the BeginForm
helper does with the <form>
element.
You could use a templated Razor delegate
instead:
public static class HtmlExtensions
{
public static HelperResult Secure(this HtmlHelper html, Func<object, HelperResult> template)
{
return new HelperResult(writer =>
{
if (condition here)
{
template(null).WriteTo(writer);
}
});
}
}
and then:
@Html.Secure(
@<div>
You will see this text only if some condition is met
</div>
)
Post a Comment for "Capture Wrapped Content In BeginForm Style Disposable Html Helper"