我正在尝试编写一个BeginForm样式的html帮助器,它使用IDisposable来包装其他代码。我希望帮助器只在满足某个条件时呈现包装的代码(例如,用户具有某种特定的角色)。
我认为我可以简单地在Begin方法中切换context.Writer并在Dispose方法中将其切换回来。下面的代码编译并运行,但包装的内容在所有情况下都会呈现。如果我单步执行它,包装的内容不会写入新的StringWriter,因此不在我的控制之内。
public static IDisposable BeginSecure(this HtmlHelper html, ...)
{
return new SecureSection(html.ViewContext, ...);
}
private class SecureSection : IDisposable
{
private readonly ViewContext _context;
private readonly TextWriter _writer;
public SecureSection(ViewContext context, ...)
{
_context = context;
_writer = context.Writer;
context.Writer = new StringWriter();
}
public void Dispose()
{
if (condition here)
{
_writer.Write(_context.Writer);
}
_context.Writer = _writer;
}
}
我正在尝试使用html助手做什么?
我知道razor中的声明性html助手可能会有效,但如果可能的话,我会更喜欢标准的html助手方法,因为MVC3中的razor助手的app_code限制。
答案 0 :(得分:9)
实际上你可以有条件地隐藏具有类似BeginForm结构的内容。它只涉及搞乱内部StringBuilder:
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();
}
}
然后你只需要创建一个HtmlHelper来创建上述对象的实例
public static class RestrictedHelper
{
public static Restricted RestrictedContent(this HtmlHelper htmlHelper, bool allow)
{
return new Restricted(htmlHelper, allow);
}
}
用法如下:
@using (var restricted = Html.Restricted(true))
{
<p>This will show up</p>
}
@using (var restricted = Html.Restricted(false))
{
<p>This won't</p>
}
优点:
使用ASP.Net MVC 4进行测试
答案 1 :(得分:6)
您无法有条件地呈现返回IDisposable
的辅助方法的正文内容。它将始终呈现。当您想要使用using
帮助程序对BeginForm
元素进行自定义标记时,可以使用此样式的帮助程序。
您可以使用templated Razor delegate
代替:
<form>
然后:
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);
}
});
}
}