2010-11-14 38 views
4

我刚刚安装了ASP.NET MVC 3 RC以尝试升级MVC 2网站。我遇到了一个渲染问题,我使用从头开始创建的MVC 3项目,在网站外部重新渲染。在ASP.NET MVC 3 Razor View Engine中渲染损坏使用自定义HTML扩展

这里是我的剃刀CSHTML观点:

@using Mvc3RCTest.Helpers 

<h2>Demo Render Bug</h2> 

<div class="content"> 
@{ Html.RenderTest(); } 
</div> 

RenderTest是定义的HTML扩展如下:

using System.Web; 
using System.Web.Mvc; 

namespace Mvc3RCTest.Helpers 
{ 
    public static class TestHtmlExtensions 
    { 
     public static void RenderTest(this HtmlHelper html) 
     { 
      HttpResponseBase r = html.ViewContext.HttpContext.Response; 
      r.Write("<ul>"); 
      for (int i = 0; i < 10; ++i) 
      { 
       r.Write("<li>" + i + "</li>"); 
      } 
      r.Write("</ul>"); 
     } 
    } 
} 

当这个被渲染时,HTML如下所示:

<ul><li>0</li><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul> 
<h2>Demo Render Bug</h2> 

<div class="content"> 
</div> 

如您所见,RenderTest HTML扩展的输出错误地发出了之前其余的Razor模板。看起来好像Razor渲染引擎正试图缓存整个输出,而不知道HTML扩展可以直接写入输出。

有没有其他人看到过这个问题?任何人都知道如何解决这个问题,而不必重做所有的HTML扩展,不要直接写入输出?

回答

9

不幸的是,你的助手应该写入ViewContext.Writer,像这样

public static void RenderTest(this HtmlHelper html) 
{ 
    var writer = html.ViewContext.Writer; 
    writer.Write("<ul>"); 
    for (int i = 0; i < 10; ++i) 
    { 
     writer.Write("<li>" + i + "</li>"); 
    } 
    writer.Write("</ul>"); 
} 

事在ASPX视图引擎可能已经为你服务,但是这是纯属巧合。并不是说剃刀本身就是在缓存任何东西。由于Razor页面是从内到外的渲染,因此只有当您到达最顶层布局页面时,它才会将内容写入临时缓冲区,缓冲区会在适当的时间写入响应流。如果您直接写入响应流,那么您将按顺序写入内容。

+0

谢谢,你保存了一天。因为这个,我正要放弃升级到MVC 3! – DSO 2010-11-14 09:00:55

+0

实际上,我希望Razor引擎不会缓存我所有的Write调用......执行写操作与返回字符串的整个目的是在大量数据时更高效。 – DSO 2010-11-14 09:15:03

3

Html助手通常会返回一个MvcHtmlString而不是直接写入响应。直接写入响应让我想起了老牌经典的WebForms控件:-)

public static MvcHtmlString RenderTest(this HtmlHelper html) 
{ 
    var ul = new TagBuilder("ul"); 
    var sb = new StringBuilder(); 
    for (int i = 0; i < 10; ++i) 
    { 
     var li = new TagBuilder("li"); 
     li.SetInnerText(i.ToString()); 
     sb.Append(li.ToString()); 
    } 
    ul.InnerHtml = sb.ToString(); 
    return MvcHtmlString.Create(ul.ToString()); 
} 

作为一个侧面说明了TagBuilder类已被移至System.Web.WebPages装配在MVC 3 RC所以一定要确保这个被引用。

+1

在渲染大量数据(如大表或列表)时,最好写入输出流。它通过减少每个请求的内存占用量来提高可伸缩性。它还减少了客户端的响应时间,因为他们开始快速接收数据,而不是阻塞,直到所有渲染缓存在字符串中。 – DSO 2010-11-14 09:09:01

相关问题