First blog post ever! Let’s see how it’ll turn out.
So I’ve been playing with Html & Js for a while as it’s the “cool” thing these days. It was all working fine , a few Ajax calls here and there etc. But after a while , I noticed this one weird or maybe even buggy behavior.
There is this one controller where I check out the incoming requests and if everything is OK then I redirect it to another action. And then in that second action I want to check if it’s an Ajax request or not , since I just want to send back raw page ( without Master Page ) if it is indeed an Ajax request.
When I did that , I thought my first action would run and just switch to the second action when it comes to RedirectToAction.
But it turns out when you use RedirectToAction method , MVC actually finishes the first Action , even fires up the OnResultExecuting / OnResultExecuted method and then starts a new procedure , creates a new controller and runs that second action etc.
Well OK , what’s the problem? The problem is , the request I’m working on is an Ajax request. But when I redirect to that second action , using RedirectToAction() , the second action runs as if the request is just an ordinary ( non-Ajax ) request. So when you go check Request.IsAjaxRequest() in that second action , you’ll get a huge , sad FALSE. Long story shorter ; RedirectToAction loses the Ajax Flag!
After Googling about it a little , I found a StackOverflow Q&A for this issue. Unfortunately I can’t seem to find it at the moment but I’ll add the link whenever I do. The suggested and accepted solution was extending the default controller to preserve the Ajax flag by using TempData. Obviously TempData is a great fit for the job as it’s created and used to store information that can be consumed in subsequent requests , right?
Unfortunately there were some little bugs with the suggested solution in that Stackoverflow Q&A so I just write my own little custom controller for it.
Enough with the talk eh?
public class FaschoController : Controller { private const string AjaxTempKey = "__isAjax"; public bool IsAjax { get { return (Request.IsAjaxRequest() || TempData.ContainsKey(AjaxTempKey)); } } private void PreserveAjaxFlag() { if (IsAjax) { TempData[AjaxTempKey] = true; } else if (TempData.ContainsKey(AjaxTempKey)) { TempData.Remove(AjaxTempKey); } } protected override void OnResultExecuting(ResultExecutingContext filterContext) { if (filterContext.Result is RedirectToRouteResult) { PreserveAjaxFlag(); } base.OnResultExecuting(filterContext); } }
First of all , I’m really bad at naming stuff so I just go with the first thing came to my mind. And what are we doing here , extending , strengthening the “Controller” right? THE Controller… So yeah , Fascho Controller! It’s silly I know, anyway…
So what’s going on here? We just override the OnResultExecuting method and make sure that it saves the Ajax flag to somewhere safe ( well safer than a controller which will be destroyed in seconds ) in case it’s a RedirectToRouteResult.
protected override void OnResultExecuting(ResultExecutingContext filterContext) { if(filterContext.Result is RedirectToRouteResult) { PreserveAjaxFlag(); } base.OnResultExecuting(filterContext); }
Remember we’re still in first action so Request.IsAjaxRequest() will return true. Then we put this answer into TempData with a static key defined in our controller.
private void PreserveAjaxFlag() { if (IsAjax) { TempData[AjaxTempKey] = true; } else if (TempData.ContainsKey(AjaxTempKey)) { TempData.Remove(AjaxTempKey); } }
And we’re done with the first action! Now when MVC redirect to second action , you’ll see that standard Request.IsAjaxRequest() will return FALSE but if you check our new IsAjax property , it’ll go check and return the TempData value we saved earlier. And NOW you can handle the request properly in your second action!
One more thing tho , it may or may not be necessary ( depending on your project ) but I also like to remove that Ajax key in TempData myself , just in case.
if(filterContext.Result is ViewResult) { TempData.Remove(AjaxTempKey); }
If you add this to OnResultExecuting part , it’ll remove the key whenever our application returns a view , which generally means we’re kinda done with the request and returned a proper response.
I’ll extend FaschoController even more in future , there are some other stuff I want to throw in Controller , mainly just to clean my Actions and get ride of some repetitive logic.
Visual Studio 2010 Solution