2

I like the idea of Steven Sanderson's Partial Requests in http://blog.stevensanderson.com/2008/10/14/partial-requests-in-aspnet-mvc/ and I'm trying to get it to work with Razor pages. Unfortunately it writes it to the top of the page, instead of where I actually want it to be in the document. I'm guessing the problem is similar to the one answered here: ASP.Net MVC 3 Razor Response.Write position but I don't know how to get around it.

Can anyone supply me with a workaround? Failing that, is there simply another good technique for rendering the contents of another action in a view, without that view having to know about the action?

Community
  • 1
  • 1
NickL
  • 1,870
  • 2
  • 15
  • 35
  • Just out of interest are you using Html.RenderPartial? And if so, I would try using Html.Partial instead since RenderPartial will write directly to the response and Partial will return an MvcHtmlString which may be processed differently if you have a number of loops going on. – SGB Nov 26 '11 at 17:46
  • In this instance I'm using the html helper illustrated in the blog post, which calls Invoke on the PartialRequest object (the partial view is then written directly, so not returning anything). The problem I have is that the action I'm invoking has an AuthorizeAttribute attached to prevent it being shown entirely if certain users are logged on, which is why I can't use Partial or RenderPartial – NickL Nov 26 '11 at 18:05

1 Answers1

1

Yes, it is possible.

As I'm sure you're now aware the Razor view engine writes to temporary buffers before writing to the response stream, which is why when you invoke another action the markup gets written to the response out of order.

The workaround that I've used in the past is to temporarily redirect any writes to the response to a MemoryStream while you are trying to render another action, and then creating a MvcHtmlString from the contents of the MemoryStream.

So something like:

public class HttpResonseCapture : IDisposable
    {
        private readonly MemoryStream _stream = new MemoryStream();
        private readonly Stream _originalStream;
        private readonly HttpContextBase _httpContext;

        public HttpResponseCapture(HttpContextBase httpContext)
        {
            _httpContext = httpContext;
            _originalStream = httpContext.Response.OutputStream;
            httpContext.Response.OutputStream = _stream;
        }

        public MvcHtmlString ToHtmlString() 
        {
            return MvcHtmlString.Create(Encoding.Unicode.GetString(_stream.ToArray()));
        }

        public void Dispose()
        {
            _httpContext.Response.OutputStream = _originalStream;
            _stream.Dispose();
        }
    }

Can be used like so:

using (var responseCapture = new HttpResponseCapture(httpContext))
{
   // Call other action here
   var result = responseCapture.ToHtmlString();
}
Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
  • Thanks for the response. I don't think it's possible to write/read directly to the outputstream, so how do you manage to replace it? – NickL Dec 01 '11 at 18:29