Click here to Skip to main content
15,894,095 members
Articles / Programming Languages / C#

View, View Controller, Model Controller, Model (VVCMCM) Pattern

Rate me:
Please Sign up or sign in to vote.
3.00/5 (1 vote)
18 Mar 2012CPOL11 min read 18.7K   200   16  
The MVC Pattern was first conceptualized assuming all the three actors were present at one place. Since Web Applications have both a client and a server this needs to be applied differently without technology bias.
using System;
using System.Web;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;

using VVCMCM.ModelControllers;

namespace VVCMCM
{
    public class ModelAsynOperation : IAsyncResult
    {

        private bool _completed;
        private Object _state;
        private AsyncCallback _callback;
        private HttpContext _context;

        bool IAsyncResult.IsCompleted
        { 
            get 
            { 
                return _completed; 
            } 
        }



        public ModelAsynOperation(AsyncCallback callback, HttpContext context, Object state)
        {
            _callback = callback;
            _context = context;
            _state = state;
            _completed = false;
        }

        public void StartAsyncWork()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null); 
        }

        private void StartAsyncTask(Object workItemState)
        {
            try
            {

                String method = String.Empty;
                String modelController = String.Empty;
                String customModelControllerAssembly = String.Empty;
                String action = String.Empty;
                String contentType = String.Empty;
                String format = String.Empty;
                NameValueCollection parameters = null;
                Type modelControllerType = null;
                String content = String.Empty;
                Object modelControllerInstance = null;


                //Sample URL to test this handler replace with the virtual directory if required
                //http://localhost/VVCMCM/ModelController.rspx?method=get&controller=Entity&action=Search&format=xml&firstname=alfred&lastname=anton
                //query string expected
                //method=get&controller=Entity&action=Search&format=xml&firstname=alfred&lastname=anton

                //TODO try to get this from the http header
                method = _context.Request.QueryString["method"];

                //get the model controller for the request       
                modelController = _context.Request.QueryString["controller"];

                //check if there is a customization assembly to call
                customModelControllerAssembly = _context.Request.QueryString["controllerAssembly"];

                
                if (String.IsNullOrEmpty(modelController))
                {
                    //return a server error status code as there is no controller present
                    _context.Response.StatusCode = 500;
                }
                else
                {
                    //add the namespace for the controller
                    //modelController = String.Concat("VVCMCM.ModelControllers.", modelController);

                    action = _context.Request.QueryString["action"];

                    //this can come from query string or form post
                    format = _context.Request["format"];

                    //check if an action tag is present
                    if (String.IsNullOrEmpty(action))
                    {
                        action = "view";
                    }

                    //check if format tag is present
                    if (String.IsNullOrEmpty(format))
                    {
                        format = "plain";
                    }

                    contentType = GetContentType(format);

                    //check to see if this is a form post
                    if (method.Equals("post"))
                    {
                        parameters = _context.Request.Form;
                    }
                    //else get the parameters from the query string
                    else
                    {
                        parameters = _context.Request.QueryString;
                    }


                    //check if there is customization present
                    if (!String.IsNullOrEmpty(customModelControllerAssembly))
                    {
                        //load the assembly and then take the type
                        Assembly customization = AppDomain.CurrentDomain.Load(customModelControllerAssembly);
                        modelControllerType = customization.GetType(modelController);

                    }
                    else
                    {
                        //take it type from the current assembly
                        modelControllerType = Type.GetType(modelController);
                    }

                    //check if type is present
                    if (modelControllerType != null)
                    {
                        
                        modelControllerInstance = Activator.CreateInstance(modelControllerType);
                    }

                    if (modelControllerInstance != null)
                    {
                        _context.Response.ContentType = contentType;

                        content = modelControllerType.InvokeMember(action, BindingFlags.Default | BindingFlags.InvokeMethod, null, modelControllerInstance, new Object[]{parameters}) as String;

                        //TODO caching logic

                        _context.Response.Write(content);
                    }
                    else
                    {
                        throw new ArgumentNullException(modelController);
                    }
                    

                }
            }
            catch
            {
                //dont throw
                //remove the content and give an error status
                _context.Response.Clear();
                
                _context.Response.StatusCode = 500;
            }
            finally
            {
                _completed = true;
                _callback(this);
            }
        }




        #region IAsyncResult Members

        public object AsyncState
        {
            get
            { 
                return _state; 
            }
        }

        public WaitHandle AsyncWaitHandle
        {
            get 
            {
                return null;
            }
        }

        public bool CompletedSynchronously
        {
            get 
            {
                return false;
            }
        }

        //split the query string into name values pairs
        private Dictionary<String, String> GetParametersDetails(HttpContext context)
        {
            Dictionary<String, String> parameters = null;
            //its possible that the action query string would also be counter
            if (context.Request.QueryString.Count > 0)
            {
                parameters = new Dictionary<String, String>();
                foreach (String key in context.Request.QueryString.Keys)
                {
                    if (key != "action" && key != "controller")
                    {
                        parameters.Add(key, context.Request.QueryString[key]);
                    }
                }
            }

            if (parameters.Count == 0)
            {
                parameters = null;
            }

            return parameters;

        }


        //obtain the content type to be sent
        private String GetContentType(string format)
        {
            String contentType = String.Empty;

            switch (format)
            {
                
                case "xml":
                    contentType = "text/xml";
                    break;                
                case "json":
                case "plain":
                    contentType = "text/plain";
                    break;
                case "html":
                default:
                    contentType = "text/html";
                    break;
            }
            return contentType;
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Riversand Technologies Inc
India India
Head of Engineering at Riversand Technologies Inc.

Comments and Discussions