Pau*_*les 9 html-helper asp.net-mvc-3
我正在尝试编写一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试用html帮助器做什么?
我知道razor中的声明性html助手可能会工作,但如果可能的话,我会更喜欢标准的html助手方法,因为MVC3中的razor助手的app_code限制.
Moe*_*eri 10
实际上,您可以使用类似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();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你只需要创建一个HtmlHelper来创建上述对象的实例
public static class RestrictedHelper
{
public static Restricted RestrictedContent(this HtmlHelper htmlHelper, bool allow)
{
return new Restricted(htmlHelper, allow);
}
}
Run Code Online (Sandbox Code Playgroud)
用法如下:
@using (var restricted = Html.Restricted(true))
{
<p>This will show up</p>
}
@using (var restricted = Html.Restricted(false))
{
<p>This won't</p>
}
Run Code Online (Sandbox Code Playgroud)
好处:
用ASP.Net MVC 4测试
您无法有条件地渲染辅助方法返回的正文内容IDisposable.它将始终呈现.当你想using用一些自定义标记包装块的主体时,你可以使用这种类型的帮助器,例如BeginForm帮助器与<form>元素一起使用.
你可以用一个templated Razor delegate代替:
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);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
@Html.Secure(
@<div>
You will see this text only if some condition is met
</div>
)
Run Code Online (Sandbox Code Playgroud)