czwartek, 8 października 2009

Conversation (from Seam Framework) in ASP.NET MVC (Part 1)

Recently I faced a problem of implementing an conversation in ASP.NET.
The original I based on is explained here: http://docs.jboss.org/seam/2.2.0.GA/reference/en-US/html/conversations.html . To start with let's explain what conversation is. When users browses some of web pages, the context of all the way he went, an the conditions he chose will be saved in a context - conversation context. This context shouldn't depend on browser window, so i.e. opening web page in new browser window shouldn't break the conversation context.
To explain conversation in real world let's assume that user browses our page in such a way:
1) chooses product catalog
2) narrows product list by specifying some conditions (for example price, color)
3) views single product
4) shows product images.

All the way (this 4 steps) are a conversation. We can then show links in breadcrumb, so that user with one click, can come back from step 4 to step 1.
I assumed that if user goes back (by clicking on breadcrumb) all further steps will be forgotten.
There is my solution:
a) Firstly I created an attribute, that I will decorate all the actions, which I want to be placed In conversation context.
b) Add this attribute to some controller's actions.
c) Create an conversation manager, which will take care of managing conversations.
there can be a lot of conversations, each of it will be identified by parameter cid (conversation id) in requested url. d) Create an breadcrumb, which will take information about browsed pages both from Web.sitemap file and my conversation context.

ad.a)
Listing 1: Conversation Attribute implementation
    /// 
    /// Attribute adding Conversation context to actions
    /// 
    public class Conversation : ActionFilterAttribute, IActionFilter
    {
        HashSet _Types;

        public HashSet Types
        {
            get { return _Types; }
            set { _Types = value; }
        }


        public Conversation(params CType[] types)
        {
            _Types = new HashSet();
            foreach (var item in types)
            {
                _Types.Add(item);
            }
        }

        #region IActionFilter Members

        void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
        {
            
        }

        /// 
        /// Called when [action executing]. Saves conversation context to session.
        /// 
        /// The filter context.
        void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
        {
            ConversationManager cMgr = new ConversationManager(filterContext.HttpContext, Types);
        }

        #endregion
    }

As you can see this attribute will take in it's constructor list of CTypes (conversation types). This types will indicate if page begins conversation or if opening web page with different attributes will erase previous element in conversation context or will add new (if the local path of requested page is the same).
In line 37, when an actions is being executed I create an conversation manager which will take care of managing conversation.
Listing 2: Conversation Types enum
      
      /// Describes type of conversation
      /// 
      public enum CType
      {
          /// 
          /// Begins new conversation context
          /// 
          Begin,
          /// 
          /// Joins conversation for the same Requested action, but with new parameers
          /// 
          Join,       
      }

ad. b)
Listing 3: Example of using Conversation attribute:
[Conversation(CType.Begin, CType.Join)]  
    public ActionResult Index(SearchParams searchParameters)
    {
      // Your action code
      return View();
    }
This is an example of using Conversation attribute.
The rest of implementation will be placed in next post.

Brak komentarzy: