The Magic Behind MVP / MVC Frameworks

One of the things I learned at DevConnections 08 is the magic behind ASP.NET MVC, and how it actually works. Beside the UrlRouting (which you can do with HttpModule stuff), it's pretty easy and relies a lot on Activator.CreateInstance(). As seen in my post about creating a csv from list, you can read about it here.

The magic is...shhh...

To programmatically create the worker class based on the url.

magic mvc

Yeah, no-DUH you say. Well it took MS this long to come up with it for public consumption when MVC has been around for decades. Anyhooo.

NOTE: I'm more of an MVP guy, so this is geared toward using the MVP's Presenter rather than the MVC's Controller. They're similar patterns, 'cept MVP is a bit more decoupled (and deprecated...), so in my example below, you can replace 'Presenter' with 'Controller' if it makes you fuzzy, because really, that's where all the work gets done.

Here we go.

mvc is on fire!A request comes in for blah.com/hotguitars.aspx. Your UrlRouting can match the url up with the correct view [handler] and rewrite its path to that page handler. In this case, I'd most likely use the DefaultView since the page lives off of the root (/).

On PageLoad the presenter factory is going to take the url and try to figure out which class to instantiate [return] to make the contents for the view. Each of the classes returned implement Presenter, which implements IPresenter... so I can code to the interface, which is nicer. (Notice the interfaces. I'm an interface kinda dude, because they're hot when it comes to testing).

Ok, so here's the little POC for you.

    // Presenter class implements this because all *Presenter
    // classes need to have a DoIt() method
    public interface IPresenter
    {
        void DoIt();
    }
 
    public class Presenter : IPresenter
    {
        public Presenter() { }
        public virtual void DoIt() { }
    }
    public class PresenterFactory
    { 
        //return the url minus hyphens
        private static string GetPresenterName(Regex re, string url)
        {
            return re.Match(url).Groups[1].Value.Replace("-","");
        }
        //get the url
        private static Regex rePage = 
new Regex(@"/(.+?)\.aspx", RegexOptions.IgnoreCase);

This is the sexiness....

        public static Presenter GetPresenter(Page page)
        {
            // this is blah.com/hotguitars.aspx
            string rewrittenUrl = page.Request.RawUrl;
            string presenterName = GetPresenterName(rePage, rewrittenUrl);    
            //here is where you make sure you have a HotGuitarsPresenter
            string className = "BunchaJunk.Presenters." + presenterName + "Presenter";
            // get the type, throw error, and ignore case
            Type type = Type.GetType(className, true, true);
            // create an instance of the correct Presenter/Controller and return it
            return (Presenter)Activator.CreateInstance(type, new object[] { page });
        }
    }
    public interface IBasicPage
    {
        string HtmlTitle { get; set; }
        string HtmlMetaKeywords { get; set; }
        string HtmlMetaDescription { get; set; }
        string MainContent { get; set; }
    }
    public class HotGuitarsPresenter : Presenter
    {
        private IBasicPage ibp;
        public HotGuitarsPresenter(IBasicPage ibp)
        {
            this.ibp = ibp;
        }
        public override void DoIt()
        {
            ibp.HtmlMetaDescription = "Hot stuff!";
            ibp.HtmlMetaKeywords = "jackson, paul reed smith";
            ibp.HtmlTitle = "Here are the hottest guitars at csharptocsharp!";
            ibp.MainContent = "paul reed smith, jackson, gibson";
        }
    }
 
 

Here is how it is called from aspx code behind
    public partial class _Default : Page, IBasicPage
    {  
        protected void Page_Load(object sender, EventArgs e)
        {
            //coding to the interface is the cat's meoooooooooooow
            IPresenter p = PresenterFactory.GetPresenter(this);
            p.DoIt();
        }
        public string HtmlTitle { get; set; }
        public string HtmlMetaKeywords{get;set;}
        public string HtmlMetaDescription { get; set; }
        public string MainContent{get;set;}
    }

Here is how it's used in the aspx
<title><%=HtmlTitle%></title>

That is all!

kick it on DotNetKicks.com

Tags:

About Brian


profile for bluevoodoo1 on Stack Exchange, a network of free, community-driven Q&A sites

Brian Canzanella brings you nifty tips and tricks for most things .NET. read more...

Readers / Stuff