Asp.net-Mvc-3
在 BeginForm 樣式的一次性 html 助手中擷取包裝的內容
我正在嘗試編寫一個 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 限制。
您不能有條件地呈現輔助方法返回的主體內容
IDisposable。它會一直渲染。當你想using用一些自定義標記包裝塊的主體時,你可以使用這種風格的助手,比如BeginForm助手對<form>元素所做的。您可以使用 a
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); } }); } }進而:
@Html.Secure( @<div> You will see this text only if some condition is met </div> )
實際上**,您可以**使用類似 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> }好處:
- 編寫自定義邏輯以顯示/隱藏您的內容並將其傳遞給 Restricted 建構子。
- Restricted 對像中的公共屬性可以在視圖中的程式碼塊中訪問,因此您可以在那裡重用計算值。
用 ASP.Net MVC 4 測試