Hanalei, Hawaii Monday, February 08, 2010

Some Thoughts on Oxite

Recently, the Platform D&E (developer evangelists) group released Oxite, a CMS/blog application that is summarily described thus: Oxite is an open source, standards compliant, and highly extensible content management sample that can run anything from blogs to big web sites. We know this because it runs MIX Online.

Recently, the Platform D&E (developer evangelists) group released Oxite, a CMS/blog application that is summarily described thus:

Oxite is an open source, standards compliant, and highly extensible content management sample that can run anything from blogs to big web sites. We know this because it runs MIX Online.

UPDATE: It's been suggested that the last paragraph of this post is a bit confusing. People have asked me if "using" Oxite (in other words installing as your blog or something on your intranet) is a bad idea and I've consistently said "No - it works like it was designed to work so go for it". Some have read that to mean "aside from Oxite's issues, it's still a good example". That's not at all what I meant. To make it clear - I'd recommend waiting until the design issues are fixed before you download the tool and use it, period.

The purpose for releasing Oxite is laid out on the CodePlex site:

What is this?

This is a simple blog engine written using ASP.NET MVC, and is designed with two main goals:
  1. To provide a sample of 'core blog functionality' in a reusable fashion. Blogs are simple and well understood by many developers, but the set of basic functions that a blog needs to implement (trackbacks, rss, comments, etc.) are fairly complex. Hopefully this code helps.
  2. To provide a real-world sample written using ASP.NET MVC.

We aren't a sample-building team (more on what we are in a bit). We couldn't sit down and build this code base just to give out to folks, so this code is also the foundation of a real project of ours, MIX Online. We also created this project to be the base of our own personal blogs as well so you'll probably see our blogs on the list of sites running Oxite soon.

In summary: Oxite is a pretty cool ASP.NET MVC application written by the guys who are putting together the MIX online site. Their goal, which is awesome, is to "share the love" and hand out the source for what they've created, which they feel is a good example of a real-world ASP.NET MVC application and I must say - it's pretty groovy of those guys to turn their code out so people can see how they've done what they've done.

Some Side Effects
One thing that's really interesting about working at Microsoft is that when you write something on your blog, or issue some code, others can construe it as "Microsoft has stated publicly that..." and "Today Microsoft Released...". Case in point:

There's a good deal of blogging going on in the PHP/LAMP community as well, talking about how Microsoft is "taking on WordPress", etc. You can imagine how that rolls out :). I've talked to the guys who wrote Oxite and this is not what they intended at all. In fact if you read what they've said - all they want to do is help others who are using ASP.NET MVC. It just happens that it's being taken in some different ways.

This quote, from the InformationWeek article , is something I identify with:

Earlier in the week when I met with Microsoft, I surprised them -- especially Peter Galli -- when I mentioned Oxite. It was so new even the folks in the Platform Strategy division hadn't yet heard of it, but they were mighty interested in it once they knew. (I chalk this up to the sheer size of Microsoft as a company: it's often hard if not downright impossible to know what everyone else is doing.)

Indeed, it is a large company and it's particularly hard to coordinate efforts sometimes. When you're working on as many technical fronts as Microsoft is, you're bound to cross swords.

I can also say that you can lump me in the "surprised" crowd. I had no idea this was going on. Not that I sit in on every meeting (sort of hard where I live), but I am on the ASP team and read the distribution lists and never once did I see a reference to an MVC blogging platform. It happens and all in all I'm grateful for more sample code.

My goal with the Storefront series was to explore real world issues with respect to MVC - so what I think might be good is to go over some of the different approaches the Oxite team has taken, versus what I have done with the Storefront, and why I think some of the design choices they made should be revisited.

What I'm mainly trying to address is the confusion some developers may have with Oxite and what they may have seen with the Storefront stuff as well as things that Stephen Walther talks about in his tutorials (Stephen and I talk quite often).

Critical Suggestions
Before I get into the details, there is one critical issue I need to touch on, since it's a very important issue with ASP.NET MVC - and that is Cross-site Scripting vulnerability. As you may know, ASP.NET MVC doesn't use Server Controls, and therefore we lose the luxury of automatic Html Encoding of page output. The Html Helpers encode the output of the controls, but if you hand-code the HTML on your page, you can accidentally forget this and get yourself in trouble.

Critical Item: XSS Vulnerability
I've let the team know about what I've found here, and they've committed a fix already. I'm letting you know this in case you've downloaded a version without the fix.

It goes without saying that The ASP.NET MVC team is committed to reducing exposure to XSS vulnerabilities, myself included. There are many places we can improve on - primarily our samples and demos! We don't take XSS lightly and know that it's a big issue. Please understand that we recognize this is a big, big concern.

That said, I did find an XSS vulnerability on the Comments section - specifically where you add your URL to the site. The team has since encoded this so if you don't have the latest - go get it! If you're using this software live (which you shouldn't - it's a developer's preview) then you need to go Html.Encode() the comment.Url on the comments page (see below).

Architectural Discussion
One thing I've found is that architectural discussions are just not short on opinion. One goal of mine with respect to the Storefront is to go and find out what I didn't know, and to see if I could simplify the choices in front of me. Nothing's perfect, that's for sure, but there are some standard choices you can make with respect to architecture to keep you from inventing something new. In general my feeling with respect to Oxite is that they're trying something new.

Issue 1: Repositories,Singletons, and ProviderModel Confusion
The Oxite team are dividing up the data access into Repositories, which is a good thing for testability and is a nice concise pattern to work with. What's not so good is that this scheme is then wrapped in the ProviderModel, which is responsible for configuring and setting a subset of Repositories (but not all of them). Generally speaking, Providers are usually instantiated once (Singleton) from the ConfigurationSettings that you provide (doing so more than once is a perf hit, usually). I'm still not completely clear what's happening with the Provider stuff - right now it's using a Singleton pattern but the locking has been commented out - which leads me to believe that the Provider is instantiated for every Controller call, which means multiple provider instances per application, which means ... general confusion:

    public static class IDataProviderConfigurationExtensions

    {

        //private static IOxiteDataProvider providerInstance;

        //private static readonly object loctite = new Object();

        public static IOxiteDataProvider GetInstance(this IDataProviderConfiguration dataProviderConfiguration)

        {

            //if (providerInstance == null)

            //{

            //    lock (loctite)

            //    {

            //        if (providerInstance == null)

            //        {

                        string[] typeParts = dataProviderConfiguration.Type.Split(',');

                        string typeName = Assembly.CreateQualifiedName(typeParts[1].Trim(), typeParts[0].Trim());

                        Type type = Type.GetType(typeName);

 

                        return (IOxiteDataProvider)Activator.CreateInstance(type, new object[] {

                            ConfigurationManager.ConnectionStrings[dataProviderConfiguration.ConnectionStringName].ConnectionString });

            //        }

            //    }

            //}

 

            //return providerInstance;

        }

    }

My suggestion here is that Repositories don't need Providers - you can use Dependency Injection to get around this.

Architectural Choices

Issue 2: Controllers as Business Layer
One of the things that the Oxite team decided to do was to separate the Controllers and Views into another Project for what I can only assume is the separation of business logic from view logic. This can lead to some confusion since Controllers are meant to handle application flow - not necessarily business logic.

This decision is causing an excess of code in the form of Controller Actions. Some actions have more than 100 lines of code. In general your Controller should concern itself with 7-10 actions only - and these should revolve around CRUD. In general, if you find yourself needing 12-20 Actions on your Controller, it's time to refactor a bit and split out your functionality.

I would suggest splitting this into a specific layer, letting the Controllers do what they do the best: control the flow of the application based on user input.

Issue 3: Controller Segregation
This sort of bleeds into Issue 2, but is slightly different - and I couldn't really think of a better word than "Segregation". Currently in Oxite there is a Controller named "AdminController" which handles all things for the Admin "section" of the site. In general this is not a good approach, since "Admin" crosses every single responsibility on the site (Posts, Comments, Pingbacks, etc) and therefore requires a Constructor From Hell. Ideally you can correspond a Controller to a Repository, and if you're using a DDD approach, you might want to have that correspond to an Aggregate Root.

In general the web site's structure feels a lot like a standard Web Application. That's not a bad thing of itself - however it's confusing, especially if people are wanting to learn from a sample application. For instance, I mentioned the "AdminController" above, it has Views named "EditPost" and "ViewPost", "AreasEdit" etc. I understand from reading the code what they were after - however each of these things (Post, Area, Comment, Permalink, Tag, etc) needs its own Controller with a small set of actions devoted to working directly with the data and its repository.

Issue 4: ViewData as Trashcan
When you write 10 lines of "ViewData["blah"]=blah", then you're effectively abusing the ViewData and you're trying to do too much. The idea is to keep your Controllers and Views light, quick, and easy so you can test each of them and be sure of the output. In the case of the AdminController's ViewPost() action, you would need to evaluate 10 separate bits of ViewData in order to test the state of your Controller. This is not ideal since more moving parts equal more bugs.

Issue 5: BaseController Script/CSS Lists
BaseControllers can cut down on code quite a lot, however using them to control script output is not a good idea since this is the concern of the View, not the Controller (which scripts are needed is not an application flow concern). These can go into a Helper class.

Issue 6: Helpers - Use Them To Clear Up View Logic
There are a number of Extension method files that can be used throughout the application and that's a Good Thing. However the Oxite team stopped just a little short of using them to help clean up the Views. For instance, the XSS injection point I spoke of above uses this code to output the URL of the comment author (I added the Html.Encode element around the URL):

       <% if (comment.Published != null) { %><div><a name="<%= comment.Published.Value.GetPermalinkHashValue() %>"></a></div><% } %>

        <div class="name">

            <div><%= string.IsNullOrEmpty(comment.CreatorUrl) ?

                     Html.Gravatar(comment.CreatorHashedEmail, comment.CreatorName, "48", Config.Site.GravatarDefault as string) :

                     Html.Link(Html.Gravatar(comment.CreatorHashedEmail, comment.CreatorName, "48",

                        Config.Site.GravatarDefault), comment.CreatorUrl.CleanHref(), new { rel = "nofollow", @class = "avatar" })%>

                    </div>

            <p class="comment"><strong><% if (!string.IsNullOrEmpty(comment.CreatorUrl)) { %>

            <a href="<%=Html.Encode(comment.CreatorUrl) %>"><% } %>

            <%=comment.CreatorName.CleanText() %>

            <% if (!string.IsNullOrEmpty(comment.CreatorUrl)) { %></a>

            <% } %></strong><% if (comment.Published != null) { %><span>

            <%= Localize("said") %><br /> <a href="#<%=ConvertToLocalTime(comment.Published.Value).GetPermalinkHashValue() %>">

            <%=ConvertToLocalTime(comment.Published.Value).ToString("MMMM dd, yyyy")%></a></span><% } %></p>

        </div>

        <div class="text">

            <p><%=comment.Body %></p>

        </div><%

        if (userCanEdit)

        { %>

    </div><%

        }

The big point I'd like to make here is that the #3 comment I've received about ASP.NET MVC is that it looks like "Spaghetti Code from 1999". I've really tried to address this many times and I'd like to suggest to the Oxite team that they focus on this - understanding the UI logic is critical, and using Html Helpers to do it is very important.

Summary
Really, Oxite is a fine application that I think could benefit from a little tweaking before we dub it a "ASP.NET MVC Sample Application". It's hard to write a post like this without sounding negative, and I can't stress enough how important it is that my comments be taken as trying to be helpful - not demeaning.

Should I Use Oxite?
Of course! Nothing that I've said here means you can't use it as a tool to run your site. It's a great application in that it does what it says it will do - nothing is a show-stopped (except for handling the XSS bits). MIX is a beautiful site and shows what you can do with MVC.

Originally I drew a distinction between "using" and "learning from/starting with" and it's been pointed out to me (by quite a few people) that this is confusing. So I'll say this: wait a bit. Wait until some of the design issues are fixed and the approach is a bit more solid.

Overall Oxite is a great idea and I'd LOVE to see more Open Source goodness come out of the Blue Monster.


chrisntr - December 13, 2008 - And since it is on Codeplex - anyone can contribute and take some of your suggestions and run with them. I agree there's a little too much logic in the views than their should be and would be great to see that handled a little better.
Kevin Dente - December 13, 2008 - Look at you, with your aggregate roots and separated concerns. Go on with your bad DDD self. ;)
robconery - December 13, 2008 - I just KNEW someone was going to say something :p. Krikey.
Todd Smith - December 13, 2008 - Issue 2: I would suggest splitting this into a specific layer, letting the Controllers do what they do the best: control the flow of the application based on user input.



Shouldn't the business layer (aka workflow) determine the page flow?



Issue 4: I agree on the usage of ViewData. So far the only time I use it is for redirecting to another page.



I guess I could also pass it via new {Id = Id.Value, form = form}?



{

TempData["form"] = form;

return RedirectToAction ("Edit", "Account", new {Id = Id.Value});

}



Issue 6: "Spaghetti" Helpers



With a little bit of code formatting its a lot less spahetti like http://img392.imageshack.us/img392/6350/aspxcz3.jpg



If this snippet is only ever going to appear in this once place wouldn't a helper just be moving it someplace else? It's already in a separate user control.

robconery - December 13, 2008 - Business Logic != Application Flow. The clicking of buttons and handling of

input is the Controller's deal - it just hands off the information from the

user to the Biz layer, then gets data back from it to display to the user.

If the app's small this can be the same thing. If it's larger, it's akin to

processing an order (calling out to a Credit card company, etc) in the

Controller, which is not good.

Usage of ViewData is fine to send data to the View. The problem is when you

do it 10 times in one Action :).



Finally - yes formatting make it look nicer. The idea with a Helper is that

you can pull out reusable bits, such as "DecideTextOrUrl(string text, string

url)". This is off the top of my head - but there's a lot you can do to help

this page :)
ricky - December 13, 2008 - Hey Rob,



Shouldn't Url.Encode (HttpUtility.UrlEncode(url)) be used for URL's instead of Html.Encode ? It isn't the same.



For example: < is < in HTML, and %3C in a URL



Thanks for taking the time to review the architecture and share your thoughts.

ricky - December 13, 2008 - i guess the encoding of this comment form is weird too :)



i typed < i '& l t ;' in HTML
Todd Smith - December 13, 2008 - Business Logic != Application Flow



I guess that's what I'm struggling with. In some cases a single page action could result in 10 different responses on where to go next. That is considered application flow isn't it? And in non-trivial cases you'll want your Business Logic (BS) deciding what happens and when.



If you click checkout the BS checks if you're a registered user and if not sends you to /account/create/?mode=checkout

If you click checkout the BS checks if you have one-click enabled, it processes your order and lands you on an order confirmation page

If you click checkout the BS checks if you're a first time customer and sends you to the apply for credit card offer prior to doing the normal checkout process

etc. etc.



Blogs, forums, search engines, news sites, galleries, etc. don't usually contain this kind of business logic so the controller can end up responsible for the majority of application flow. But in a real business application that responsibility should lie elsewhere which makes the following statement misleading:



"this can lead to some confusion since Controllers are meant to handle application flow - not necessarily business logic."



Then the question becomes, how to expose routing abilities to your business layer. BTW I'm new to this area so I may have it all backwards, upside down and in reverse.
ricky - December 13, 2008 - Oh there is also Html.AttributeEncode() which might be the right one.. sigh, now I am confused :)

Torkel - December 14, 2008 - You beat me to it, I was thinking of writing a "Oxite Code Review" post.



When I checkout the code from codeplex I was expecting a quality ASP.NET MVC app (code wise), I was really surprised see 100+ lines of code in the controller action methods, time for some serious refactoring? Also there were no unit tests for controller actions :/



DougWilson - December 14, 2008 - I took a wander through Oxite when it first became public. I "smelled" a lot of the things you point out but being new to MVC I wasn't very sure of myself. Thank you for yet another tactful and excellent post.
Derik Whittaker - December 14, 2008 - Rob,



Nice writeup, you saved me the effort (along with scores of others) as you pretty much nailed this on the head.



Although I commend the team for sticking their neck out there and posting code, they should have asked for more/better guidance before creating this app with MVC.



Daniel Auger - December 14, 2008 - Their current stab at the persistence provider model, not including the aborted singleton code, would have been considered a good practice a few years ago before DI gained ground in .net. However, I am surprised that they aren't caching the constructor and newing up the providers off of that instead of using Activator every time. The performance would be much better, and MS apparently considered this to be a best practice at one time.



(see last code block on the page)

http://msdn.microsoft.com/en-us/library/ms972370.aspx

Javier Lozano - December 14, 2008 - Yet again, Rob, you've proven that you're a ninja in disguise. :)



First of all, I love what the Oxite guys did, since they're helping evangelize the "word of MVC". However, as you've mentioned in the post, that comes at a price. I think you, me and other people that are passionate about MVC succeeding have said enough about "guidance can be be good or bad" once released out in the wild, so I'll leave the discussion at that.



I think one important thing to note is that Oxite serves as a good example of viewing an MVC implementation from a "WebForms state of mind". This is just my thoughts but I think it would be beneficial to take Oxite and ALTer it a bit to show the flexibility of the MVC framework.
Colin Jack - December 14, 2008 - Great post.



I noticed a lot of twitter talk about the quality of the Oxite design/code so went and had a look. I'm stunned, I had a look at a couple of the controllers and to me the code is really poor. You mentioned the AdminController and I totally agree about the design but the code also really needs to have a few refactorings applied to it.



I also think that before doing an open source MVC application, particularly one that could be seen as a sample, you have to ensure you put some effort in to learn the mindset behind MVC and why people use it. Just looking at the code I'm not entirely sure the authors have gone through that process and I'm hoping people like yourself will manage to educate them.





"Ideally you can correspond a Controller to a Repository, and if you're using a DDD approach, you might want to have that correspond to an Aggregate Root."



I agree that an MVC based approach should result in controllers that have a strong relationship to the model (which AdminController does not), but I'd question the way you are bringing in DDD directly.



I think you need to remember that DDD is not specifically for designing GUI centric models. It is true that some of the DDD patterns can be used on heavily GUI focussed apps I think you need to consider whether the M in MVC is really a DDD domain model. I'd argue that in many cases it won't be, and that you might be better having a view/presentation model that you use from the view/controller. This view/presentation model might sit on top of a DDD domain model though....
Colin Jack - December 14, 2008 - "I think one important thing to note is that Oxite serves as a good example of viewing an MVC implementation from a "WebForms state of mind"."



Nicely summed up and it would be great to see how the app changes as the authors go out and learn more about MVC/TDD/SOC and the many other topics that were not emphasized widely within the WebForms community.
Colin Jack - December 14, 2008 - "time for some serious refactoring"



Looking at the code I'm thinking that the biggest bang for your buck code-wise might come from the authors sitting down with a copy of Refactoring and working out how to improve the controller code. The lack of tests would be another worry, as would be the design of those "repository" classes, but fundamentally the code itself is un-necessarily old school.
robconery - December 14, 2008 - I should have known better than to mention DDD in this post :).
Colin Jack - December 14, 2008 - You're right, you can't win :)



I only mention it because I did actually work on an e-commerce type project with ASP.NET MVC recently and I still found having a separate presentation model sitting on top of the domain helped a lot not least in that it simplified the real domain model and let me keep it a lot simpler and more pure.



For example value object is a key DDD pattern but it can prove to be inconvenient from a GUI perspective as when you pass invalid data into a value objects constructor it'll raise an exception. A simple solution is to use code-generation to create presentation specific equivalents for the value object. This presentation specific class can be more forgiving, for example it might have getters and setters and a method to tell you what the broken rules for the object are.
alanstevens - December 14, 2008 - Hey Rob, excellent post! I think you get the tone exactly right. I wish more criticism in our community was delivered with this level of maturity. You found significant flaws, yet you managed to point them out without making ad-hominem attacks against the authors.



We need an equivalent in the .NET community of minswan (Matz is nice, so we are nice) in the ruby community. I vote for rinswan (Rob is nice, so we are nice). ;-)



++Alan
Scott - December 14, 2008 - Ricky: Now, Url.Encode is meant to prepare a string to be passed in a url e.g if you have a domain or page name with a space in it "http://foo.com/My page.html", which is a valid filename, and you Url.Encode it it will come out like this "http://foo.com/My%20Page.html". If you Url.Encode a string for display on a page, say to prevent script embedded in the string from executing, the script will still execute.



Html.Encode is used often to prevent script attacks because it converts the brackets to their appropriate character entities. e.g. < goes to & l t ; (with no spaces) which will prevent the script execution.
Andy - December 15, 2008 - I think Oxite seems pretty good and by far the most "complete" MVC application I have seen. Congratulations to them. Sure they will refactor the code in due course. They've demonstrated solutions for some things which are still too difficult using ASP.NET MVC, like Ajax and modularity. And the code is 10 times better than the average project developed by developers in the Microsoft ecosystem. I'm keen that MVCStorefront and Oxite become the new Commerce and Community Startkit style applications. It's great if their styles and approaches differ. Finally, I certainly do though agree that the "new CMS" and "new Wordpress" spin in the (blog) press is off the mark. But, hey, they're only blogs giving comments, and they'll soon realise where Oxite is targetted - as a good complete sample of an MVC application.



Even Microsoft developers seem to be getting way too jumpy about this all. Bottom line, it's a sample, it's open source. Again, well done to the Mix team.
Glenn - December 15, 2008 - I may be missing the point of Oxite but I wanted to publish it to the web and play around with it.



I set it up on port 83 and did a redirect with isa server 2006 (and all the other things for publishing)



I can run it up by clicking the gren play button on visual studio 2008 but when I try to access it over the web I get this error....

System.Exception: No site or redirect was found.



Any ideas ?
Chris - December 15, 2008 - "I think you need to consider whether the M in MVC is really a DDD domain model..."



right on, Colin! I am seeing the same thing as I drive out an MVC app using DDD. The "domain model" is different from the MVC "View model".
Scott Bradley - December 15, 2008 - Glen, open your web.config and look for


The host needs to be the url you are accessing it with.

Brian Henderson - December 15, 2008 - Great informative writeup.. a link to this post should be added on http://www.Codeplex.com/Oxite home page "Some Thoughs on Oxite, to know before getting started". An additional link explaining how to contribute (code) would also helpful.
ricky - December 16, 2008 - Thanks for the clarification!
sixYo - December 19, 2008 - wonderful
Jarrett - December 24, 2008 - It's amazing all the publicity that Oxite has gotten. The more of these code reviews the better it will become as long as the benevolent dictator allows it. I wish BlogSvc could get one of these code reviews. I'm hoping it would be a bit more favorable as we took a bunch of hints from Storefront series.
Kobe &ndash; the ASP.NET MVC sample application &laquo; Bogdan Brinzarea&#8217;s blog - April 19, 2009 - [...] Oxite was the first try to get an official ASP.NET MVC application. Let’s just say that it was wrong from many points of view including the fact that the guys that were actually involved in developing ASP.NET MVC were not even consulted. Many guys from Microsoft stood up saying that it was wrong: Phil Haack, Glenn Block and Rob Conery. [...]
Rolex4You 4Free - June 5, 2009 - Best Rolex deal at my homepage!
Get Rolex with 50% discount!
Rolex for YOU from US
chrisntr - December 14, 2008 - And since it is on Codeplex - anyone can contribute and take some of your suggestions and run with them. I agree there's a little too much logic in the views than their should be and would be great to see that handled a little better.
Kevin Dente - December 14, 2008 - Look at you, with your aggregate roots and separated concerns. Go on with your bad DDD self. ;)
robconery - December 14, 2008 - I just KNEW someone was going to say something :p. Krikey.
Todd Smith - December 14, 2008 - Issue 2: I would suggest splitting this into a specific layer, letting the Controllers do what they do the best: control the flow of the application based on user input.

Shouldn't the business layer (aka workflow) determine the page flow?

Issue 4: I agree on the usage of ViewData. So far the only time I use it is for redirecting to another page.

I guess I could also pass it via new {Id = Id.Value, form = form}?

{
TempData["form"] = form;
return RedirectToAction ("Edit", "Account", new {Id = Id.Value});
}

Issue 6: "Spaghetti" Helpers

With a little bit of code formatting its a lot less spahetti like http://img392.imageshack.us/img392/6350/aspxcz3...

If this snippet is only ever going to appear in this once place wouldn't a helper just be moving it someplace else? It's already in a separate user control.
robconery - December 14, 2008 - Business Logic != Application Flow. The clicking of buttons and handling of
input is the Controller's deal - it just hands off the information from the
user to the Biz layer, then gets data back from it to display to the user.
If the app's small this can be the same thing. If it's larger, it's akin to
processing an order (calling out to a Credit card company, etc) in the
Controller, which is not good.
Usage of ViewData is fine to send data to the View. The problem is when you
do it 10 times in one Action :).

Finally - yes formatting make it look nicer. The idea with a Helper is that
you can pull out reusable bits, such as "DecideTextOrUrl(string text, string
url)". This is off the top of my head - but there's a lot you can do to help
this page :)
Todd Smith - December 14, 2008 - Business Logic != Application Flow

I guess that's what I'm struggling with. In some cases a single page action could result in 10 different responses on where to go next. That is considered application flow isn't it? And in non-trivial cases you'll want your Business Logic (BS) deciding what happens and when.

If you click checkout the BS checks if you're a registered user and if not sends you to /account/create/?mode=checkout
If you click checkout the BS checks if you have one-click enabled, it processes your order and lands you on an order confirmation page
If you click checkout the BS checks if you're a first time customer and sends you to the apply for credit card offer prior to doing the normal checkout process
etc. etc.

Blogs, forums, search engines, news sites, galleries, etc. don't usually contain this kind of business logic so the controller can end up responsible for the majority of application flow. But in a real business application that responsibility should lie elsewhere which makes the following statement misleading:

"this can lead to some confusion since Controllers are meant to handle application flow - not necessarily business logic."

Then the question becomes, how to expose routing abilities to your business layer. BTW I'm new to this area so I may have it all backwards, upside down and in reverse.
ricky - December 14, 2008 - Hey Rob,

Shouldn't Url.Encode (HttpUtility.UrlEncode(url)) be used for URL's instead of Html.Encode ? It isn't the same.

For example: < is < in HTML, and %3C in a URL

Thanks for taking the time to review the architecture and share your thoughts.
ricky - December 14, 2008 - i guess the encoding of this comment form is weird too :)

i typed < i '& l t ;' in HTML
ricky - December 14, 2008 - Oh there is also Html.AttributeEncode() which might be the right one.. sigh, now I am confused :)
Scott - December 14, 2008 - Ricky: Now, Url.Encode is meant to prepare a string to be passed in a url e.g if you have a domain or page name with a space in it "http://foo.com/My page.html", which is a valid filename, and you Url.Encode it it will come out like this "http://foo.com/My%20Page.html". If you Url.Encode a string for display on a page, say to prevent script embedded in the string from executing, the script will still execute.

Html.Encode is used often to prevent script attacks because it converts the brackets to their appropriate character entities. e.g. < goes to & l t ; (with no spaces) which will prevent the script execution.
ricky - December 16, 2008 - Thanks for the clarification!
Torkel - December 14, 2008 - You beat me to it, I was thinking of writing a "Oxite Code Review" post.

When I checkout the code from codeplex I was expecting a quality ASP.NET MVC app (code wise), I was really surprised see 100+ lines of code in the controller action methods, time for some serious refactoring? Also there were no unit tests for controller actions :/
Colin Jack - December 14, 2008 - "time for some serious refactoring"

Looking at the code I'm thinking that the biggest bang for your buck code-wise might come from the authors sitting down with a copy of Refactoring and working out how to improve the controller code. The lack of tests would be another worry, as would be the design of those "repository" classes, but fundamentally the code itself is un-necessarily old school.
Doug Wilson - December 14, 2008 - I took a wander through Oxite when it first became public. I "smelled" a lot of the things you point out but being new to MVC I wasn't very sure of myself. Thank you for yet another tactful and excellent post.
Derik Whittaker - December 14, 2008 - Rob,

Nice writeup, you saved me the effort (along with scores of others) as you pretty much nailed this on the head.

Although I commend the team for sticking their neck out there and posting code, they should have asked for more/better guidance before creating this app with MVC.
Daniel Auger - December 14, 2008 - Their current stab at the persistence provider model, not including the aborted singleton code, would have been considered a good practice a few years ago before DI gained ground in .net. However, I am surprised that they aren't caching the constructor and newing up the providers off of that instead of using Activator every time. The performance would be much better, and MS apparently considered this to be a best practice at one time.

(see last code block on the page)
http://msdn.microsoft.com/en-us/library/ms97237...
Javier Lozano - December 14, 2008 - Yet again, Rob, you've proven that you're a ninja in disguise. :)

First of all, I love what the Oxite guys did, since they're helping evangelize the "word of MVC". However, as you've mentioned in the post, that comes at a price. I think you, me and other people that are passionate about MVC succeeding have said enough about "guidance can be be good or bad" once released out in the wild, so I'll leave the discussion at that.

I think one important thing to note is that Oxite serves as a good example of viewing an MVC implementation from a "WebForms state of mind". This is just my thoughts but I think it would be beneficial to take Oxite and ALTer it a bit to show the flexibility of the MVC framework.
Colin Jack - December 14, 2008 - "I think one important thing to note is that Oxite serves as a good example of viewing an MVC implementation from a "WebForms state of mind"."

Nicely summed up and it would be great to see how the app changes as the authors go out and learn more about MVC/TDD/SOC and the many other topics that were not emphasized widely within the WebForms community.
Colin Jack - December 14, 2008 - Great post.

I noticed a lot of twitter talk about the quality of the Oxite design/code so went and had a look. I'm stunned, I had a look at a couple of the controllers and to me the code is really poor. You mentioned the AdminController and I totally agree about the design but the code also really needs to have a few refactorings applied to it.

I also think that before doing an open source MVC application, particularly one that could be seen as a sample, you have to ensure you put some effort in to learn the mindset behind MVC and why people use it. Just looking at the code I'm not entirely sure the authors have gone through that process and I'm hoping people like yourself will manage to educate them.


"Ideally you can correspond a Controller to a Repository, and if you're using a DDD approach, you might want to have that correspond to an Aggregate Root."

I agree that an MVC based approach should result in controllers that have a strong relationship to the model (which AdminController does not), but I'd question the way you are bringing in DDD directly.

I think you need to remember that DDD is not specifically for designing GUI centric models. It is true that some of the DDD patterns can be used on heavily GUI focussed apps I think you need to consider whether the M in MVC is really a DDD domain model. I'd argue that in many cases it won't be, and that you might be better having a view/presentation model that you use from the view/controller. This view/presentation model might sit on top of a DDD domain model though....
robconery - December 14, 2008 - I should have known better than to mention DDD in this post :).
Colin Jack - December 14, 2008 - You're right, you can't win :)

I only mention it because I did actually work on an e-commerce type project with ASP.NET MVC recently and I still found having a separate presentation model sitting on top of the domain helped a lot not least in that it simplified the real domain model and let me keep it a lot simpler and more pure.

For example value object is a key DDD pattern but it can prove to be inconvenient from a GUI perspective as when you pass invalid data into a value objects constructor it'll raise an exception. A simple solution is to use code-generation to create presentation specific equivalents for the value object. This presentation specific class can be more forgiving, for example it might have getters and setters and a method to tell you what the broken rules for the object are.
Chris - December 15, 2008 - "I think you need to consider whether the M in MVC is really a DDD domain model..."

right on, Colin! I am seeing the same thing as I drive out an MVC app using DDD. The "domain model" is different from the MVC "View model".
Alan Stevens - December 14, 2008 - Hey Rob, excellent post! I think you get the tone exactly right. I wish more criticism in our community was delivered with this level of maturity. You found significant flaws, yet you managed to point them out without making ad-hominem attacks against the authors.

We need an equivalent in the .NET community of minswan (Matz is nice, so we are nice) in the ruby community. I vote for rinswan (Rob is nice, so we are nice). ;-)

++Alan
Andy - December 15, 2008 - I think Oxite seems pretty good and by far the most "complete" MVC application I have seen. Congratulations to them. Sure they will refactor the code in due course. They've demonstrated solutions for some things which are still too difficult using ASP.NET MVC, like Ajax and modularity. And the code is 10 times better than the average project developed by developers in the Microsoft ecosystem. I'm keen that MVCStorefront and Oxite become the new Commerce and Community Startkit style applications. It's great if their styles and approaches differ. Finally, I certainly do though agree that the "new CMS" and "new Wordpress" spin in the (blog) press is off the mark. But, hey, they're only blogs giving comments, and they'll soon realise where Oxite is targetted - as a good complete sample of an MVC application.

Even Microsoft developers seem to be getting way too jumpy about this all. Bottom line, it's a sample, it's open source. Again, well done to the Mix team.
Glenn - December 15, 2008 - I may be missing the point of Oxite but I wanted to publish it to the web and play around with it.

I set it up on port 83 and did a redirect with isa server 2006 (and all the other things for publishing)

I can run it up by clicking the gren play button on visual studio 2008 but when I try to access it over the web I get this error....
System.Exception: No site or redirect was found.

Any ideas ?
Scott Bradley - December 15, 2008 - Glen, open your web.config and look for <oxite><site name="Oxite Sample" host="http://yourhosthere.com"

The host needs to be the url you are accessing it with.
Brian Henderson - December 16, 2008 - Great informative writeup.. a link to this post should be added on http://www.Codeplex.com/Oxite home page "Some Thoughs on Oxite, to know before getting started". An additional link explaining how to contribute (code) would also helpful.
sixYo - December 20, 2008 - wonderful
Jarrett - December 24, 2008 - It's amazing all the publicity that Oxite has gotten. The more of these code reviews the better it will become as long as the benevolent dictator allows it. I wish BlogSvc could get one of these code reviews. I'm hoping it would be a bit more favorable as we took a bunch of hints from Storefront series.
Gecko