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.
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:
- 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.
- 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:
- Microsoft launches open-source blogging platform (CNET)
- Microsoft’s Next Dabble In Open Source: Oxite (InformationWeek)
- Microsoft develops open-source content-management system (Mary Jo Foley on ZDNet)
- Microsoft takes dead aim at WordPress (Ed Bott)
- WordPress Could Face Serious Competition, From Microsoft (The Inquisitor)
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.






