MaVeriCk – An Open-Source CMS written in ASP.Net MVC

This is a big post, I know, but I think it’ll be worth it.  If you don’t have time to read it all, I organized it by importance, so the important stuff is at the top anyway :).

I’ve been hinting for a while that I’ve been working on a secret side project using ASP.Net MVC that was sort-of related to DotNetNuke.  Well, it’s finally time for me to put some code out there :).  Today, I published a source code package containing version 0.1 of MaVeriCk, a Content Management System written in ASP.Net MVC.  I’ll explain what it is and how to get started in this blog post.

Warning: MaVeriCk is nowhere near finished, and very much an alpha (maybe even a pre-alpha ;).  Major features are completely missing (such as user management, and any useful modules, see below for details)

Disclaimer: This project has NO RELATION to the DotNetNuke project.  While I am a DNN Core Team member, this is purely a personal side-project.  DotNetNuke has inspired some of the things I’ve done in MaVeriCk, but that’s the extent of the connection between the two.

What is MaVeriCk?

Maverick is an open-source Content Management System in the style of *Nuke applications such as DotNetNuke.  For the rest of this post, I’m going to assume you’re fairly familiar with that style of application.  Basically, users create pages and drop little widgets (or “Modules”) onto those pages to provide features like a Blog, Message Board, or even just a block of HTML.

Where (and how) do I get it?

The project is hosted on GitHub (http://github.com/anurse/MaVeriCk/) so you can feel free to clone the repository and hack away there.  Alternatively, if you either don’t have Git or don’t want to bother with getting the whole repository, you can download version 0.1.0, from the downloads section: http://github.com/anurse/MaVeriCk/downloads.  Also on the downloads page are the release notes for this version which include a full installation guide.  Unfortunately, there is no automated installation system, but the steps are quite straightforward if you’re familiar with ASP.Net.

Feel free to post comments on this blog, or send me email at: andrew AT andrewnurse DOT net

(After all, I’m just a junior programmer just out of college and don’t purport to be an expert in the various development patterns and architectures, so if you think something doesn’t look right, please let me know!)

How does it work?

The rest of this post will be a, very short, introduction to the Module Framework provided by Maverick.  I’ll be posting much more detailed information about the guts of Maverick later on, this is just a taste.  Feel free to send me email (see above) if you have questions about the rest of the architecture, and don’t be afraid to dive into the code!

Let’s start by taking a look at a MaVeriCk page:

image

Here, we see a page with two modules.  The first module is an instance of the “Current Time” Module Application, the second is an instance of the “Claim Dumper” Module Application.  A Module Application is an MVC Application, with its own Controllers and Views, which handles requests for a particular type of module.  If you’re familiar with DNN, the “Module Application” is analogous to the “Module Definition” concept in DNN.

Here’s a look at the code for the Current Time Module Application:

[Export(typeof(ModuleApplication))]
[ModuleApplication(ApplicationId, ApplicationName, "1.0.0.0", "Displays the Current Time", "Maverick", "~/Modules/CurrentTime/Content/Images/Icon.png")]
public class CurrentTimeModuleApplication : ModuleApplication {
    private const string ApplicationId = "A1FE2A31-0BC9-4B12-9B81-3B75C098EB33";
    private const string ApplicationName = "Current Time";

    protected override string FolderPath {
        get { return "CurrentTime"; }
    }

    protected internal override void Init(MaverickApplication application) {
        base.Init(application);
        RegisterRoutes(Routes);
    }

    private static void RegisterRoutes(RouteCollection routes) {
        routes.RegisterDefaultRoute("Maverick.Web.Modules.CurrentTime.Controllers");
    }
}

Compare this with the Global.asax file with an MVC app, and you’ll find it’s very similar.  The “Init” method is equivalent to “Application_Start” and is called the first time the Module Application is run during the current ASP.Net Application’s lifetime.  Just as you would in an MVC ‘Application_Start’ method, the Current Time Application registers routes into a route table for this module application.  In this case, the module is using a helper that Maverick provides to register the default route, but if we take a look at that helper, the only difference between the standard MVC route and this route is that we require that the namespace containing the Controllers is specified:

public static void RegisterDefaultRoute(this RouteCollection routes, string routeName, string defaultController, string defaultAction, string defaultId, string[] namespaces) {
    routes.MapRoute(
        routeName,
        "{controller}/{action}/{id}",
        new {controller = defaultController, action = defaultAction, id = defaultId},
        namespaces
        );
}

(Note: there are various overrides to this method, including the one you see used by the CurrentTimeModuleApplication class above)

Routing in Maverick is a little more complex than in standard MVC applications.  I’ll go into more details on it later, but the gist of it is that a portion of the URL for a request is handled by Maverick, and the rest (if any) goes to one of the modules on the page (called the “Active” or “Selected” module).  All the other modules (referred to as “Passive” modules) get an empty URL, and their default route is run.

From there on, a module is surprisingly similar to an MVC application.  It has Controllers and Views, just like an MVC app.  The big difference is that, in most cases, the ActionResult returned by a Controller does not represent the whole page, just a fragment of it.  Maverick collects all the ActionResults for a page and then renders them out one-by-one in the correct location.  Of course there are exceptions (for example, if a Module returns a FileResult or a RedirectResult), but that’s the core of it.

Missing Features

Maverick is in an early preview state at the moment.  There is a powerful authentication model available (or “Identity” model, as I call it), but at the moment, there’s only a very simple “Debug” implementation of it (which just automatically logs you in as an Administrator).  I have a prototype system which uses the Azure Access Control Service in the code, but it is not active by default (I’ll post more about that later).

Maverick does not really include any useful modules, so you’re on your own there.  Module development is relatively simple, and will be the focus of another blog post.  Feel free to check out the other modules for more info.  The only major component of Module Development not covered in the provided sample modules is data storage.  Maverick does have a system for modules to store data in the Maverick Database, but none of the built in modules do that.

There is a very rudimentary Theming system in place to allow you to create your own templates for the site (similar to DNN Skins).

Despite being touted as a Content Management System, Maverick doesn’t actually contain any Content Management features :), no Workflow, no Versioning, no Content Approval.  However, those features are planned for the future.

If you have any other suggestions, please let me know!

Wednesday, May 20, 2009 4:49:20 AM (Pacific Standard Time, UTC-08:00)
Hi Andrew,
There is a lot of debate as to what in MVC is "better" than regular webforms (see your colleague's post - I Spose I’ll Just Say It: Still Waiting For a GOOD Reason to Learn MVC).

What do you see as the advantages that MVC gives Maverick over DNN, e.g. ease of developing modules/skins/other extensions, or URL format, or performance etc etc?

Thanks
Laurence
Wednesday, May 20, 2009 8:34:03 AM (Pacific Standard Time, UTC-08:00)
Hi Laurence

Well, first off, I started writing Maverick as a way of exploring exactly what advantages MVC might be able to bring to a CMS, and I haven't completely finished that process. Having said that, I think the key advantages MVC brings to the table is the removal of the WebForms abstraction layer. Rather than trying to take a familiar model (WinForms) and impose it on the stateless Web, MVC is a model that is designed to fit the Web directly and embrace the stateless nature of it. With MVC, modules can easily create RESTful services by simply producing controller actions which return JSON or XML. They can also take advantage of all the features the MVC model already has to offer, such as multiple view engines, routing, deep integration of dependency injection containers, etc. (granted, some of these features can be implemented in WebForms).

I use MVC primarily because I prefer that model over the WebForms model. I wrote Maverick so that other people who prefer MVC (for whatever reason) can have a more structured platform on which to develop applications. If someone is not yet convinced of MVC, I don't know if Maverick will convince them otherwise, but if they do decide that MVC is the way to go, then Maverick is here for them to use.

I'll be posting more detailed posts describing module development in Maverick later.

Hope that helps!
Friday, June 26, 2009 5:07:39 AM (Pacific Standard Time, UTC-08:00)
Hi.
I took the source. Good job. Modules follow real MVC concept. Great. But I miss two things about modules. The inter modules communication on page and module settings. Is there any plan to provide they in next releases?
Thanks.
peter
Friday, June 26, 2009 10:46:37 AM (Pacific Standard Time, UTC-08:00)
Hi peter,

At the moment, Maverick is just a little exploratory project of mine, so specific features like inter-module communication and module settings haven't been implemented. As I get time to work on it, I'll implement more and more of those features.

Glad you liked the source!
Andrew
Wednesday, July 08, 2009 12:35:19 AM (Pacific Standard Time, UTC-08:00)
Hi Andrew.

I really like your start of new framework.
I want to implement inter-module communication. I am just thinking about how to implement it. I will create another tabel "ModuleCommunication" which will contain a pair SourceModuleAction, DestinationModuleAction of page. When SourceModuleAction will be executed, all its DestinationModuleActions will be executed too. What do you think about this concept? Does it make sense? How can I solve transformation of source and destination parameters of action easily? Do you have any idea? Or do you have any better concept of implementation of inter module communication?

I want to hear your opinion about this.

Thanks.
peter
Wednesday, July 08, 2009 8:45:12 AM (Pacific Standard Time, UTC-08:00)
Hi peter,

To be honest, I haven't given much thought to Module Communication at this time, as it's a feature of DNN I have never personally used. IIRC, the purpose is to allow modules to send messages to each other, even if they aren't on the same page. Given that requirement, your model seems like a good start. If you're up for hacking it up in the code, I'd be happy to check out your implementation of Module Communication. I recommend you use GitHub and "fork" the project so you can work on the changes yourself and then I can pull your changes back into the main project very easily.

Rob Conery, lead of the SubSonic open source project, has just posted a screencast about forking SubSonic on GitHub and the process is identical to forking Maverick. You can check it out here: http://blog.wekeroad.com/subsonic/subsonic-working-with-git/

If you have further questions about Maverick or otherwise want to discuss your Module Communication ideas, you can email me at "andrew AT andrewnurse DOT net" (replace the ATs and DOTs appropriately; I'd like to avoid my address getting scraped by spambots :P)

-Andrew
Comments are closed.