ASP.NET MVC Conversational Session

By | March 24, 2013

I’m proudly presenting you my first self-made NuGet package. 🙂

NuGet: ASP.NET MVC Conversational Session (Nuget)
GitHub: ASP.NET MVC Conversational Session (GitHub)

I’ve created a small extension for ASP.NET MVC which simplifies the session handling in tabbed browsing scenarios.
The extension ensures, that your session data won’t be overwritten. For example:

  • Page 1: Contains a list of entities. When the user clicks on “Edit” a new window/tab gets opened.
  • Page 2 (edit page): Data is stored in session because the edited data needs to be displayed on page 3,4 etc. On the last page, the user decides if he wants to save the data.

Now if the users tries to edit two entities at same time (two different window/tabs), the session data will overwritten. There will be always one entity in the session.

The “ASP.NET MVC Conversational Session” extension helps out in such situations. It allows to create “conversations”.
Features of a conversation:

  • Contains contiguous data.
  • Isolated. Data cannot be overwritten.
  • Parallel conversations possible.
  • Two types of conversations: Controller and Name-scoped

In the scenario above, the page 2 (edit page) should store data in a conversation to prevent problems when the user works with multiple windows/tabs.

The code is fairly easy to use. Here are some examples:

Controller scoped conversation
First you have to set the conversation attribute on the class. You can access the conversation with the extension method “Conversation()”.

[Conversation]
public class PersonController : Controller
{
    protected HttpConversationalSessionState Conversation
    {
        get { return this.Conversation(); }
    }

    public ActionResult Index()
    {
	    this.Conversation["MyKey"] = "Conversation data";
        return View();
    }
    
    // Clear conversation data after this call. (Declarative)
    [Conversation(End=true)]
    public ActionResult SiteTwo()
    {
        // Read data from the CURRENT conversation.
	    var data = this.Conversation["MyKey"];
       
        // Ending current conversation the imperative way
        // is possible too.
        this.Conversation.End();
        
        return View();
    }
}

Name scoped conversation
Works exactly the same way as in the example above with a small difference. You have to define the name of the scope in the conversation attribute. In this example the conversation with the name “demo” can be access from multiple controllers.

[Conversation(Scope = "Demo")]
public class Scope1Controller : Controller
{
    protected HttpConversationalSessionState Conversation
    {
        get { return this.Conversation(); }
    }

    public ActionResult Index()
    {
        this.Conversation["MyKey"] = "Conversation Data";
        return View();
    }
}

[Conversation(Scope = "Demo")]
public class StillScope1Controller : Controller
{
    protected HttpConversationalSessionState Conversation
    {
        get { return this.Conversation(); }
    }

    public ActionResult Index()
    {
		var data = this.Conversation["MyKey"];
        return View();
    }
}

The conversation attribute can also be defined on the controller action. In such scenario, only name scoped conversations makes sense.

The view
Now here comes a part I try to improve in the next releases. 🙂
Every conversation has a identifier which must be passed from the client. That means, we have to add the identifier to the links and form actions. Here are some examples:

@using System.Web.Mvc.Conversation.View;

@Html.ActionLink("Site two", "SiteTwo").AsConversational()

@using (Html.BeginForm("Confirm", "Person", Html.CreateRouteValues()))
{
  ...
}

The “AsConversational” extension method adds the conversation identifier to the url.
And the same for forms with: “CreateRouteValues”.

If the Conversation Session could run inside ASP.NET MVC (core), we wouldn’t take care about the indentifier. (Link generation would happen in the background.)
But because we are running outside the core (extension), we must add the identifier on our own.

Feel free to test/use this extension.
Here is a small demo app: Conversation Session Demo

And… Your feedback is highly appreciated! 😉