Simple Map Generator Part 1

Simple Map Generator – Introduction

OK so now that we have Amit’s blog post as a general guideline and a Voronoi diagram library , we can start coding. In this post , we’ll just create a nice Voronoi diagram and a 2D visualization of it.

First of all , we need a Voronoi diagram. We’ll throw bunch of points in an area and Bendi’s Voronoi library will calculate the edges between those points for us. And then we’ll create a better and more complicated structure so it’ll be easier to play with it in the future.

var rnd = new Random();
var points = new HashSet<BenTools.Mathematics.Vector>();

for (int i = 0; i < DotCount; i++)
{
    points.Add(new BenTools.Mathematics.Vector(rnd.NextDouble() * MapSize,
    rnd.NextDouble() * MapSize));
}

VoronoiGraph voronoiMap = Fortune.ComputeVoronoiGraph(loadMapParams.Points);

VoronoiGraph is a class from Bendi’s library. It inclused edges and vertices of the voronoi diagram.

Edges have all the data we need so we’ll use them but before that , if you have seen any Voronoi diagrams before , you may ahve noticed that area sizes varies a lot. And since extremely small or big areas looks pretty bad in later stages , I use Lloyd’s algorithm to generate a more “balanced” diagram.

I won’t go into details but in general , all you have to do is to

– generate a voronoi diagram ( using random number for first time )
– take the center points of the areas in that diagram
– regenerate the diagram with those points
– Repeat it as much as you want

After like 3-4 times , you’ll have a much better balanced diagram. If you run it too much , you’ll end up with a grid tho , so be careful. ( There is something wrong with my implementation tho , messing up after like 10 iterations. Oh well , I use 3 anyway. )

Now we a VoronoiDiagram object but it’s hardly usefull for anything. Sho now we’ll use that diagram object and create a structure pretty close to the one Amit used. We’ll create Centers ( the points we put in ) , Edges ( edges between those points ) and Corners ( where edges connect each other ) and then set some relations between them. For example , center object will have Neighbours ( centers ) , Borders ( edges ) and Corners.

As I said before , VoronoiEdges in VoronoiDiagram object has all the data we need , so we’Ll just iterate through them and get as much data as we can.

foreach (VoronoiEdge edge in voronoiMap.Edges)
{
    Corner c1 = fact.CornerFactory(edge.VVertexA[0], edge.VVertexA[1]);
    Corner c2 = fact.CornerFactory(edge.VVertexB[0], edge.VVertexB[1]);
    Center cntrLeft = fact.CenterFactory(edge.LeftData[0], edge.LeftData[1]);
    Center cntrRight = fact.CenterFactory(edge.RightData[0], edge.RightData[1]);

    c1.AddAdjacent(c2);
    c2.AddAdjacent(c1);

    cntrRight.AddCorner(c1);
    cntrRight.AddCorner(c2);

    cntrLeft.AddCorner(c1);
    cntrLeft.AddCorner(c2);

    Edge e = fact.EdgeFactory(c1, c2, cntrLeft, cntrRight);

    cntrLeft.AddBorder(e);
    cntrRight.AddBorder(e);

    cntrLeft.AddNeighbour(cntrRight);
    cntrRight.AddNeighbour(cntrLeft);

    c1.AddProtrudes(e);
    c2.AddProtrudes(e);
    c1.AddTouches(cntrLeft);
    c1.AddTouches(cntrRight);
    c2.AddTouches(cntrLeft);
    c2.AddTouches(cntrRight);
}

Pretty straight forward I guess? Create Corners , create centers , add a few relations then create the edge and then add that edges relations etc etc. Actually this is probably a lot more detailed than we need but still , it just makes everything easier in later stages.

Oh and by the way , as I mentioned before ; Bendi’s library doesn’t take map borders into account so you have to take care of it before this part. I won’t go into this here , but I added my fix function to the example solution below. It does a decent job but not perfect ( can mess up map corners etc ) so you may want to rewrite that part.

And also ; I’m skipping most of the small details in this post , like ordering area corners for visualization etc. You can find them all in the solution below.

So now we have our organized voronoi diagram but before moving any further , let’s have a look what we have done right? I’ll use an ObservableCollection to hold map items ( centers , edges , corners ) and then a ListBox ( using a Canvas as ItemConainer ) to view those items.

It seems FunnelWeblog doesn’t support XAML in posts. Whatever , now all we need is to create an ObservableCollection , fill it with our items and bind it to that ListBox.

You can find the sample solution below. It only includes the basics I described above and a 2D presentation.

Next , we’ll create the island and stuff.

Visual Studio 2010 Solution

Slide Transitions in WPF

I have been working on a small media player application on WPF these days. And since I’m going full Metro on it , I needed some good animations and transitions. 

The main idea is to have a one screen for everything and then just slide in/out whole content with the help of a little menu at the top right. This menu should have like 2-3 horizontal layers , one layer for stuff like settings , help , about etc , then another layer for main menu items , and probably a 3rd one for sub menus or player screen etc.

So whenever you click on a menu item ; the main view behind the menu ( whole application surface including that big blue “Management” title ) will slide left/right or top/bottom according to the layer and position of that item. Sounds good?

Being way too lazy to implement it myself , I started searching for a nice transition implementation and came across FluidKit. Althought it’s pretty old and seems abandoned , I decided to give it a shot. So I started playing with it and it was all going fine until I this little bug ; althought LeftToRight and RightToLeft transitions are working properly , there seems to be a problem with BottomToTop and TopToBottom transitions as they don’t work at all. Even when I set direction to BottomToTop by hand , it just ignores the direction and slides LeftToRight!

Only after wasting a few hours , I remembered it’s an open source project and decided to take a look at the code and found this little method , in SlideTransition class , which supposed to , well Prepare Storyboard ;

public override Storyboard PrepareStoryboard()
{
    Storyboard animator = (TransitionResources["SlideAnim"] as Storyboard).Clone();

    DoubleAnimation prevAnim = animator.Children[0] as DoubleAnimation;
    DoubleAnimation nextAnim = animator.Children[1] as DoubleAnimation;
    Storyboard.SetTargetName(prevAnim, "PrevElement");
    Storyboard.SetTargetName(nextAnim, "NextElement");
    prevAnim.Duration = this.Duration;
    nextAnim.Duration = this.Duration;

    // Left <-> Right transition
    if (Direction == Direction.RightToLeft)
    {
        prevAnim.From = 0;
        prevAnim.To = -1 * Owner.ActualWidth;

        nextAnim.From = Owner.ActualWidth;
        nextAnim.To = 0;
    }
    else
    {
        prevAnim.From = 0;
        prevAnim.To = Owner.ActualWidth;

        nextAnim.From = -1 * Owner.ActualWidth;
        nextAnim.To = 0;
    }

    return animator;
}

See the problem? They just totally ignored vertical animations!

Turns out that Direction Enum is used for all transitions supported by FluidKit and vertical transitions are only used in stuff like CubeTransition. So although you get intellisense for BottomToTop and TopToBottom and even set Direction to those , FluidKit doesn’t even care , doesn’t even give an exception and just plays the default LeftToRight animation!

Now that we know what the problem is , it’s pretty easy to fix it. Well just add Top&Bottom support to PrepareStoryboard method and then add a new StoryBoard for vertical animations.

First , the PrepareStoryboard Method ;

 

public override Storyboard PrepareStoryboard()
{
    Storyboard animator = null;
    if (Direction == Direction.RightToLeft || Direction == Direction.LeftToRight)
        animator = (TransitionResources["SlideAnimX"] as Storyboard).Clone();
    else
        animator = (TransitionResources["SlideAnimY"] as Storyboard).Clone();


    DoubleAnimation prevAnim = animator.Children[0] as DoubleAnimation;
    DoubleAnimation nextAnim = animator.Children[1] as DoubleAnimation;
    Storyboard.SetTargetName(prevAnim, "PrevElement");
    Storyboard.SetTargetName(nextAnim, "NextElement");
    prevAnim.Duration = this.Duration;
    nextAnim.Duration = this.Duration;

    // Left <-> Right transition
    if (Direction == Direction.RightToLeft)
    {
        prevAnim.From = 0;
        prevAnim.To = -1 * Owner.ActualWidth;

        nextAnim.From = Owner.ActualWidth;
        nextAnim.To = 0;
    }
    else if (Direction == Direction.LeftToRight)
    {
        prevAnim.From = 0;
        prevAnim.To = Owner.ActualWidth;

        nextAnim.From = -1 * Owner.ActualWidth;
        nextAnim.To = 0;
    }
    else if (Direction == Direction.BottomToTop)
    {
        prevAnim.From = 0;
        prevAnim.To = -1 * Owner.ActualHeight;

        nextAnim.From = Owner.ActualHeight;
        nextAnim.To = 0;
    }
    else if (Direction == Direction.TopToBottom)
    {
        prevAnim.From = 0;
        prevAnim.To = Owner.ActualHeight;

        nextAnim.From = -1 * Owner.ActualHeight;
        nextAnim.To = 0;
    }


    return animator;
}

So instead of ignoring vertical animations , we handle them properly and set the From&Top properties of animation according to the direction ( notice we’re using ActualyHeight instead of Width for vertical animations ).

Oh and it turns out FluidKit uses storyboards from a xaml instead of creating them in code. I played along and didn’t changed that ;

TransitionStoryboards.xaml ;

 

<Storyboard x:Key="SlideAnim">
<DoubleAnimation Duration="0:0:0.5"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)"
DecelerationRatio="1.0"/>
<DoubleAnimation Duration="0:0:0.5"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)"
DecelerationRatio="1.0"/>
</Storyboard>

<Storyboard x:Key="SlideAnimY">
<DoubleAnimation Duration="0:0:0.5"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)"
DecelerationRatio="1.0"/>
<DoubleAnimation Duration="0:0:0.5"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)"
DecelerationRatio="1.0"/>
</Storyboard>

I decided to post this as it seems there are still a few people using FluidKit out there. Hope it helps , you can find an example solution file below.

Visual Studio 2010 Solution

Simple Map Generator

So I was thinking about some game concepts last week , stealing ideas from here and there etc. One thing I noticed tho , indie games with random maps really have an advantage over professional games with static content , especially when it comes to replay value of the game. Also random map generation is a must for sandbox games like Minecraft and Terraria right? Noone would like to play same sandbox game over and over again on same map ( unless it’s HUGE ie. Eve Online )

So I decided that I need a good random map generator more than everything else , if I have a good map generator , I can build any game on it right?!

After a little search , I found the awesome blog of Amit. I remember reading his A* algorithm articles a few years ago , but somehow I totally forgot about his blog after that. It seems he just posted a new little series about random map generation a few months ago ( September 2010 ) , based on Voronoi diagrams

After reading his article and a little more about voronoi diagrams , I knew I had to do it myself so yea I have been working on it for a few days now. It’s extremely fun playing with Voronoi diagrams , shaping the land , rivers , mountains etc and create my own little island!

I’ll slowly blog about my process here , and the first step is obviously ;

Voronoi Diagrams

So what is a Voronoi diagram?

Wikipedia says ;
   In mathematics, a Voronoi diagram is a special kind of decomposition of a metric space determined by distances to a specified discrete set    of objects in the space, e.g., by a discrete set of points.

Or we can simply say ; it divides an area based on a set of points. You take a field , then throw some points in it , then create zones around those points in a way that everywhere in that zone is closer to that point than any other. An image worths thousand words right?

Looks nice isn’t it? It’s a great diagram used for lots and lots of different stuff

Now what we will do , is just throw in a few thousand dots , divide the area , then work on it as if it’s a grid. We’ll use areas to decided land type , edges to create rivers and coastline etc etc.

But since I’m more interested in creating a random map more than a basic Voronoi diagram , I decided to use a 3rd party Voronoi Diagram library to take care of that. But it turns out there isn’t many Voronoi implementations for .Net. The best I was able to find , is an implementation by BenDi , posted on CodeProject.

It’s doing a pretty good job , fast and reliable. The only problem I had , is that it only works on points and generated edges between them , there is no way to actually set area boundaries. I had to work it out myself , not a big problem but my temporary fix isn’t good enough so borders of the maps looks a bit silly. ( I’ll redo it later , I’m hardly bothered about the map borders at the moment , our island will be at the center anyway )

As I said I’ll blog more about this in future , and probably even post the project when I’m done with it.

My current process ;

 

 

Creating a custom ActionResult

OK so now that we know a little more about ActionResults , let’s create a new one! I’ll go with a simple one , a personalized ViewResult.

It’ll be pretty much like standard ViewResult. First we’ll derive a base class from ActionResult , this abstract base class will take care of the ViewData , TempData , ExecuteResult method and stuff. Then we’ll derive our ViewResult from that base class , FindView there and maybe add some logic into that.

I’ll call our little action result , “MaryLouResult” from now on. I’ve already admitted I’m bad at naming stuff , so I’ll just stick with the song ( Mary Lou – Sonata Arctica ) I’m listening at the moment.

So let’s start with MaryLouBase!

protected abstract ViewEngineResult FindView(ControllerContext context);

public override void ExecuteResult(ControllerContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException("context");
    }
    if (String.IsNullOrEmpty(ViewName))
    {
        ViewName = context.RouteData.GetRequiredString("action");
    }

    ViewEngineResult result = null;

    if (View == null)
    {
        result = FindView(context);
        View = result.View;
    }

    TextWriter writer = context.HttpContext.Response.Output;
    ViewContext viewContext = new ViewContext(context, View, new ViewDataDictionary(), TempData, writer);
    View.Render(viewContext, writer);

    if (result != null)
    {
        result.ViewEngine.ReleaseView(context, View);
    }
}

Nothing fancy here , actually I’ve just copy&pasted the ExecuteResult method of ViewResultBase class as it’s pretty straight forward. A few null checks , then FindView then ReleaseView.

You can also find ViewData and TempData implementations in ViewResultBase code or in the solution file at the bottom of this article.

Of course we could have simply used ViewResultBase and derive our MaryLouResult from that , but I just wanted to show you there is nothing magical about ViewResultBase class , you can just create another one as you like ( or totally skip it an derive your result from ActionResult ).

Now that we have a base class to handle ExecuteResult for us , all we need now is a MarylouResult with FindView method.

 

public class MaryLouResult : MaryLouResultBase
{
    private string _viewName { get; set; }
    private string _masterName { get; set; }
    private object _model { get; set; }

    public MaryLouResult(string viewName = "", string masterName = "", object model = null)
    {
        _viewName = viewName;
        _masterName = masterName;
        _model = model;
    }

    protected override ViewEngineResult FindView(ControllerContext context)
    {
        //Yeap you can get your Controller from here
        var faschoController = (context.Controller as FaschoController);

        //And check if it's an Ajax Request
        var ajax = context.HttpContext.Request.IsAjaxRequest();
        var FaschoAjax = faschoController.IsAjax;

        //Or if the user is Authenticated
        var auth = context.HttpContext.User.Identity.IsAuthenticated;
        var FaschoAuth = faschoController.IsAuthenticated();

        //Or if the user is actually an Admin
        var admin = context.HttpContext.User.IsInRole("admin");
        var FaschoAdmin = faschoController.IsAdmin();

        ViewData = new ViewDataDictionary(_model);

        //Then you can add some logic here as you like to select the view or the masterpage
        if ((context.Controller as FaschoController).IsAjax)
            _masterName = null;

        var result = ViewEngines.Engines.FindView(
        context,
        string.IsNullOrWhiteSpace(_viewName) ? ViewName : _viewName,
        _masterName
        );

        if (result.View != null)
        {
            return result;
        }

    }
}

OK so let’s see , we have a few fields for view name and master age name , then a a simple constructor and then the real part , FindView method.

FindView method gets a ControllerContext as a parameter which includes stuff like , current controller and HttpContext so we have lots of information in our hands just in case.

I really don’t have a special thing for Master pages but again the first thing came to my mind was playing with that.

As you can see you can use both HttpContext and your custom Controller ( if you have one ) from here. This means we can just check if the request is an Ajax request and change our FindView call according to that. Or maybe return Error Page if user is not authenticated?

I’ll have to say it tho , I don’t really like putting this kind of logic here. It feels out of place and I already usemy little Fascho Controller for these stuff.

This little example here was a little limited as it’s just a personalized ViewResult but actually there is literally no limit to what you can do with ActionResults. I’ll probably add a few more examples on ActionResults in future too.

You may also want to check these out ;

File Download Action Result by Phil Haack – Old but a very nice example

Image Result by Maarten Balliauw

Visual Studio 2010 Solution

Understanding ActionResults in Mvc

Almost all our Action in Mvc returns some kind of an ActionResult ( surprise! ). Or let’s say , they return a class derived from ActionResult , such as ; 

· ViewResult

· RedirectResult

· RedirectToRouteResult

· JsonResult

But how does this ActionResults work? It pretty simple actually ;

namespace System.Web.Mvc
{
    public abstract class ActionResult
    {
        public abstract void ExecuteResult(ControllerContext context);
    }
}

Told you! It’s just an abstract class with ExecuteResult function.

So let’s look into one of the most commonly used ActionResult , ViewResult and ViewResultBase ( Why I can’t link directly to a particular file  , *sigh* ).

Abstract base class , **ViewResultBase** first ;

 

namespace System.Web.Mvc
{
    using System;
    using System.Diagnostics.CodeAnalysis;

    public abstract class ViewResultBase : ActionResult
    {
        private TempDataDictionary _tempData;
        private ViewDataDictionary _viewData;
        private ViewEngineCollection _viewEngineCollection;
        private string _viewName;

        //Lots of properties below , the best part , ExecuteResult , is at the bottom

        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
        Justification = "This entire type is meant to be mutable.")]
        public TempDataDictionary TempData
        {
            get
            {
                if (_tempData == null)
                {
                    _tempData = new TempDataDictionary();
                }
                return _tempData;
            }
            set
            {
                _tempData = value;
            }
        }

        public IView View
        {
            get;
            set;
        }

        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
        Justification = "This entire type is meant to be mutable.")]
        public ViewDataDictionary ViewData
        {
            get
            {
                if (_viewData == null)
                {
                    _viewData = new ViewDataDictionary();
                }
                return _viewData;
            }
            set
            {
                _viewData = value;
            }
        }

        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
        Justification = "This entire type is meant to be mutable.")]
        public ViewEngineCollection ViewEngineCollection
        {
            get
            {
                return _viewEngineCollection ?? ViewEngines.Engines;
            }
            set
            {
                _viewEngineCollection = value;
            }
        }

        public string ViewName
        {
            get
            {
                return _viewName ?? String.Empty;
            }
            set
            {
                _viewName = value;
            }
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (String.IsNullOrEmpty(ViewName))
            {
                ViewName = context.RouteData.GetRequiredString("action");
            }

            ViewEngineResult result = null;

            if (View == null)
            {
                result = FindView(context); //this is the part we care about at the moment
                View = result.View;
            }

            ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
            View.Render(viewContext, context.HttpContext.Response.Output);

            if (result != null)
            {
                result.ViewEngine.ReleaseView(context, View); //And probably this
            }
        }

        protected abstract ViewEngineResult FindView(ControllerContext context);
    }
}

Wow , that’s a lot of code. But actually it’s just a few properties for stuff like ViewData and TempData. What we really care about here is ExecuteResult method ( at the bottom ). As you can see , ExecuteResult ( the only thing we really need for a custom ActionResult ) does 2 main things ; go find the view ( FindView ) and send it to ViewEngine ( ReleaseView ).

And the last part of our ActionResult , **ViewResult** ;

 

public class ViewResult : ViewResultBase
{
    private string _masterName;

    public string MasterName
    {
        get
        {
            return _masterName ?? String.Empty;
        }
        set
        {
            _masterName = value;
        }
    }

    protected override ViewEngineResult FindView(ControllerContext context)
    {
        ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName);
        //Obviously this gives you a good opportunity to interfere View & MasterPage selections
        if (result.View != null)
        {
            return result;
        }

        //I took out the part about error generation for now
    }
}

So all ViewResult does , is to use our ViewEngineCollection to find the page ( view ) we want. Remember , then it goes back to ViewResultBase and releases the view and we’re pretty much done with ActionResult , ViewEngine will take care of the rest.

Let’s have a look at how this all executes ;

Client Requests a Page

Controller is Created

-> Controller – OnActionExecuting runs

Action runs

->ViewResult is Created ( at return View(); )

ActionFinishes

-> Controller – OnActionExecuted runs

-> Controller – OnResultExecuting and OnResultExecuted runs

-> ViewResultBase – ExecuteResult runs

-> ViewResult – FindView runs

-> ViewResultBase send the view to ViewEngine ( ReleaseView )

Some magic happens after that which I know nothing of yet

Client gets the html , and hopefully happy now

You can also check this MSDN article about the execution process.

And Codeplex page of Asp.Net for the source code of Mvc

In next post , we’ll create a new custom ActionResult and play with it a little…

A Different Approach To Master Pages

I’ll just say it out loud , I don’t understand why do we ( or at least the MVC ) use _ViewStart to apply master pages. I just don’t get it. I mean we have a controller layer for decisions right? Why would I want to put decision logic in View layer ( or folder ).

I’m not a MVC purist , not eve close but still I don’t like this _ViewStart thing either.

@{ //Yeap it's Razor
//And we don't want any Master Page if it's an Ajax Request right?
Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
}

Another solution I learned a while ago was putting decision logic into ViewEngine. In TekPub Mastering Mvc Series , [Rob Connery](http://twitter.com/robconery) derived a personal View Engine, from WebForms view engine and put master page decision logic into that . Sounds like a nice idea isn’t it?

   

public override ViewEngineResult FindView(ControllerContext controller , string viewName, string masterName, bool useCache)
{

masterName = "DefaultMasterPage";

if(controllerContext.HttpContext.User.IsInRole("Administrator")
{
//Admin gets a special Master Page
masterName = "AdminMasterPage";
}

return base.FindView(controllerContext, viewName, masterName, useCache);
}

I like that a lot more than _ViewStart but still , adding a new View Engine and putting master page decision making process in a View Engine? Not a fan of that. Looks nice , works nice but I really don’t want to go to ViewEngine files whenever I want to change Master Page logic , feels kinda weird and out of place.

Of course , yet another and probably simplest option is to set Master Page in Controller Action while returning a view

   

public ActionResult About()
{
    return View("About","_SpecialLayout");
}

Well it’s in Controller now , right? But do we want to type the master page name in every single action? Of course not! Then we have to find a way to centralize this decision in Controller , do it once and then forget all about it right?

Just like what we did before ( in Fascho Controller post ) , we can just override OnResultExecuting method and put Master Page decision logic there! And since we’ll derive all our Controllers from this new Controller base class , it’ll be centralized , easy and pretty.

   

protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
    if (filterContext.Result is ViewResult) //if we're done and returning a view 
    {
        var temp = (ViewResult)filterContext.Result;

        if (!IsAjax) //We dont want a masterpage around data if it's an Ajax call
        if (string.IsNullOrEmpty(temp.MasterName)) // And we don't want to override if there already is a masterpage 
        {
            //MasterPage selection logic
            temp.MasterName = IsAdmin() ? "_AdminLayout" : "_Layout";
        } 
    }
    base.OnResultExecuting(filterContext);
}

Doesn’t it look good? OnResultExecuting runs right after your Action returns something ( and obviously before OnResultExecuted ) so it’s not much more different than sending MasterPage name as a parameter , yet it’s centralized and all actually inside the Controller layer. 

You can find a sample solution file below. Fascho Controller now includes both this and previous Ajax solution but I did my best to seperate them with comments so it shouldn’t be a problem.

Visual Studio 2010 Solution

Extending Controller for Better Ajax Support

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