Sitecore for Developers
Sitecore MVC Postbacks with URL Renderings
After adding a URL Rendering (which had a form on it) to the presentation details of the standard values of my template, I noticed that I could not get into the HttpPost action of my controller. I used dotPeek to decompile the Sitecore.Mvc.dll and looked at Sitecore.Mvc.Presentation.UrlRenderer and noticed that there is a call to WebUtil.ExecuteWebPage(url). This only does an HttpGet request. To submit a form with a URL Rendering I created two files:
GetUrlRenderer.cs:
using Sitecore.Data.Items;
using Sitecore.Mvc.Extensions;
using Sitecore.Mvc.Names;
using Sitecore.Mvc.Presentation;
using Sitecore.Mvc.Pipelines.Response.GetRenderer;
namespace Site.Web.Code
{
public class GetUrlRenderer : Sitecore.Mvc.Pipelines.Response.GetRenderer.GetUrlRenderer
{
protected override Renderer GetRenderer(Rendering rendering, GetRendererArgs args)
{
string url = this.GetUrl(rendering, args);
if (StringExtensions.IsWhiteSpaceOrNull(url))
return (Renderer) null;
return (Renderer) new Site.Web.Code.UrlRenderer()
{
Url = url
};
}
}
}and UrlRenderer.cs
using Sitecore.Mvc.Extensions;
using Sitecore.StringExtensions;
using Sitecore.Web;
using System.IO;
using Sitecore.Mvc.Presentation;
using System.Web;
using Sitecore.Diagnostics;
using System.Net;
using System.Collections.Specialized;
using System.Text;
namespace Site.Web.Code
{
public class UrlRenderer : Sitecore.Mvc.Presentation.UrlRenderer
{
public override void Render(TextWriter writer)
{
string url = this.Url;
if (Sitecore.Mvc.Extensions.StringExtensions.IsEmptyOrNull(url))
return;
string str = string.Empty;
if (HttpContext.Current.Request.RequestType.ToLower() == "post")
{
str = ObjectExtensions.ToStringOrEmpty<string>(ExecuteWebPagePost(url, HttpContext.Current.Request.Form));
}
else
{
str = ObjectExtensions.ToStringOrEmpty<string>(WebUtil.ExecuteWebPage(url));
}
if (Sitecore.Mvc.Extensions.StringExtensions.IsEmptyOrNull(str))
return;
writer.Write(str);
}
public static string ExecuteWebPagePost(string url, NameValueCollection form)
{
Assert.ArgumentNotNull((object)url, "url");
if (url.IndexOf("://") < 0)
url = WebUtil.GetServerUrl() + url;
WebClient webClient = new WebClient();
byte[] responseBytes = webClient.UploadValues(url, "POST", form);
string response = Encoding.UTF8.GetString(responseBytes);
return response;
}
}
}UrlRenderer has been changed to do a form submission by calling ExecuteWebPagePost instead of WebUtil.ExecuteWebPage and GetUrlRenderer has been changed to instantiate our custom UrlRenderer. To hook this up I needed to change /App_Config/Include/Sitecore.Mvc.config From:
<mvc.getRenderer><processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetUrlRenderer, Sitecore.Mvc"/></mvc.getRenderer>
To:
<mvc.getRenderer> <processor type="Site.Web.Code.GetUrlRenderer, Site.Web"/> </mvc.getRenderer>
/Views/Search/Search.cshtml:
@inherits System.Web.Mvc.WebViewPage
@{
Layout = null;
}
Route in Globals.ascx:
routes.MapRoute( "Search_UrlRendering",
"Search_UrlRendering",
new { controller = "Search", action = "Search" } );/Controllers/SearchController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Site.Web.Controllers
{
public class SearchController
{
[HttpGet]
public ActionResult Search()
{
return View();
}
[HttpPost]
public ActionResult Test(FormCollection form)
{
ViewData["search"] = form["search"];
return View();
}
}
}In Sitecore, I have created /Sitecore/Layouts/Renderings/Search_UrlRendering and set the URL field to /Search_UrlRendering which is the second parameter to my route in the Global.ascx file.
Now I am able to post back from a UrlRendering.