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.