Fixes: #U4-2460 - UmbracoHelper.RenderTemplate will now execute the complete MVC cycle when rendering MVC templates whereas before it would only execute the view which means any actionfilters, etc... applied would never have fired (as well as other things)

This commit is contained in:
Shannon
2013-07-05 14:12:31 +10:00
parent 173d388c12
commit 048480d5be
3 changed files with 94 additions and 7 deletions

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
@@ -38,6 +40,15 @@ namespace Umbraco.Web.Mvc
routeDef.Controller = controller;
}
/// <summary>
/// This is used internally purely to render an Umbraco MVC template to string and shouldn't be used for anything else.
/// </summary>
internal void ExecuteUmbracoRequest()
{
StoreControllerInRouteDefinition();
base.ProcessRequest(RequestContext.HttpContext);
}
protected override void ProcessRequest(HttpContextBase httpContext)
{
StoreControllerInRouteDefinition();
@@ -54,4 +65,6 @@ namespace Umbraco.Web.Mvc
return base.BeginProcessRequest(httpContext, callback, state);
}
}
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
@@ -11,11 +13,59 @@ namespace Umbraco.Web.Standalone
/// </summary>
internal class StandaloneHttpContext : HttpContextBase
{
private readonly string _url;
private readonly HttpSessionStateBase _session = new StandaloneHttpSessionState();
private readonly HttpResponseBase _response;
private readonly HttpRequestBase _request = new StandaloneHttpRequest();
private readonly TextWriter _writer = new StringWriter();
private readonly IDictionary _items = new Dictionary<string, object>();
public StandaloneHttpContext()
{
//create a custom response with a custom writer.
_response = new HttpResponseWrapper(new HttpResponse(_writer));
}
public StandaloneHttpContext(string url)
: this()
{
if (url == null) throw new ArgumentNullException("url");
_url = url;
_request = new HttpRequestWrapper(new HttpRequest("", _url, ""));
}
// fixme - what shall we implement here?
public override IDictionary Items
{
get { return _items; }
}
public override HttpSessionStateBase Session
{
get { return _session; }
}
public override HttpRequestBase Request
{
get { return null; }
get { return _request; }
}
public override HttpResponseBase Response
{
get { return _response; }
}
}
internal class StandaloneHttpSessionState : HttpSessionStateBase
{
}
internal class StandaloneHttpRequest : HttpRequestBase
{
}
}

View File

@@ -137,12 +137,9 @@ namespace Umbraco.Web.Templates
requestContext.RouteData.Values.Add("controller", routeDef.ControllerName);
//add the rest of the required route data
routeHandler.SetupRouteDataForRequest(renderModel, requestContext, contentRequest);
//create and assign the controller context
routeDef.Controller.ControllerContext = new ControllerContext(requestContext, routeDef.Controller);
//render as string
var stringOutput = routeDef.Controller.RenderViewToString(
routeDef.ActionName,
renderModel);
var stringOutput = RenderUmbracoRequestToString(requestContext);
sw.Write(stringOutput);
break;
case RenderingEngine.WebForms:
@@ -157,6 +154,33 @@ namespace Umbraco.Web.Templates
}
/// <summary>
/// This will execute the UmbracoMvcHandler for the request specified and get the string output.
/// </summary>
/// <param name="requestContext">
/// Assumes the RequestContext is setup specifically to render an Umbraco view.
/// </param>
/// <returns></returns>
/// <remarks>
/// To acheive this we temporarily change the output text writer of the current HttpResponse, then
/// execute the controller via the handler which innevitably writes the result to the text writer
/// that has been assigned to the response. Then we change the response textwriter back to the original
/// before continuing .
/// </remarks>
private string RenderUmbracoRequestToString(RequestContext requestContext)
{
var currentWriter = requestContext.HttpContext.Response.Output;
var newWriter = new StringWriter();
requestContext.HttpContext.Response.Output = newWriter;
var handler = new UmbracoMvcHandler(requestContext);
handler.ExecuteUmbracoRequest();
//reset it
requestContext.HttpContext.Response.Output = currentWriter;
return newWriter.ToString();
}
private void SetNewItemsOnContextObjects(PublishedContentRequest contentRequest)
{
// handlers like default.aspx will want it and most macros currently need it