Improved MVC support in Kentico CMS v7

   —   
Given the recent events around Umbraco v5, I feel that now is the right time to let you know what we are doing in regards to MVC support in version 7. Read this article to learn more...
Hi there,

What happened with Umbraco v5 is surely a shocker and should never,ever happen with any CMS, ever: http://umbraco.com/follow-us/blog-archive/2012/6/13/v5-rip.aspx.

No matter how positive they are trying to be in reverting back to v4 nor how many community members welcome that, for people who started with Umbraco v5, this is a disaster.

I must admit, however, that they were pretty brave making that decision - I cannot imagine we would even have been able to, knowing how hard it was for us to announce postponing the release of v7 from the end of June to September.

I am writing this article not only to show you how we have improved MVC support in Kentico CMS v7, but also because I feel, based on all the comments around, that there must be tons of Umbraco v5 users out there simply left behind in their MVC projects, with no idea how they should continue!

The obvious question on the table for them is "If Umbraco left people behind with v4 (with no real option to upgrade to v5), and now they are doing pretty much the same thing (maybe even worse) with v5, then can we ever trust in this solution again?".

I don't want to make this article a marketing matter, so I will stop commenting on this situation for now.

But if you know of anyone affected in this way who needs to save the future of their project, let them know that they are welcome to get on board with us to get the comfort they deserve as well as future guarantees for product updates.

Also, potential migration of the data shouldn't be a problem using our Import Toolkit application: http://devnet.kentico.com/docs/devguide/index.html?import_toolkit_initial_steps.htm

Proven by a blog post written a long time ago, we have only ever made one rewrite of our software (quite at the beginning of our story), and our architecture from that point onwards has been, and still is, ready to go through partial changes and updates without leaving anyone behind: http://devnet.kentico.com/Blogs/Martin-Hejtmanek/October-2008/Quality-of-Kentico-CMS-source-code.aspx.

Before I start to show you what is new in our MVC support, I want to make a comment to all those who were part of the decision-making process on the MVC support, regardless  of whether they provided us with detailed plans for their projects or simply posted a comment on UserVoice. When asked why we would never rewrite our engine to MVC, our answer has always been that we don't feel it is really necessary nor do we want to leave our clients behind. Now you can see why.

Our MVC support doesn't cover the whole solution because it simply isn't needed that much. All you really need, at the end of the day, is a way to build your live site pages with MVC and route to them in a nice way - of course backed up by a business layer. That is exactly what we have provided. Now it is little more than half a year since the release of Kentico CMS version 6, and there are existing projects running on MVC with Kentico CMS. We have gathered some very important feedback which we have implemented in version 7.

Let's first see how MVC works in Kentico CMS v6

Just for the reference, here is the link to the official documentation:

http://devnet.kentico.com/docs/devguide/index.html?mvc_overview.htm

Not knowing exactly how our clients would use it, we decided not to make heavy implementation in our URL rewriting, but rather provide a starter implementation and learn from it. Based on our previous experience, we expected that people would build web sites as they are used to, meaning that each document would have its own URL and place in the content tree, and then they would build a separate MVC views for that data with wildcard routing patterns.

That is why our initial support for MVC in Kentico CMS v6 was more about routing and aliasing of particular web-site sections than building pure MVC web sites. What you would typically do in version 6 would be -  preparing the content structure, and then building special pages (or reuse existing ones with aliases) to connect them to the MVC controller and view. You can see an example of that in our sample Corporate web-site -> Examples -> Development models -> MVC. If you go to the URL settings of that document, you can see the following configuration:



There are two document aliases that define an MVC route to this document; one for the listing and one for the detail. The listing alias is configured to use controller NewsMVC and execute Action (View) named List:



And the detail view uses the same controller, executing Action (View) named Detail, with a wildcard part specifying the particular news identifier, in this case interpreted as an alias of that news document:



So we are basically aliasing the documents to connect them to MVC, which is great for a live site view, but not that great for the content editor because aliases aren't used in editing modes. This means that the content editor in Page/Preview mode would still see a regular implementation of the page done through standard templates (if that even exists). That is one of the issues we came across in your feedback and wanted to improve on.

What you can see in the v6 example, is a standard portal engine page based on a text template with a description of the configuration and a link to the MVC listing URL:



Having clients who wanted to develop their web sites purely on MVC, we added a web.config settings key in hotfix 6.0.24 which allowed usage of live site URLs even in editing modes:

<add key="CMSUseLiveURLForEditing" value="true" />

If you add this, the edit, design and preview modes will use the live URL defined by the URL path or alias path of the document which will allow you to route to the MVC URL even in these editing modes.

Note that Route and MVC patterns do not use the friendly extension settings but the URL path and alias path do, so you either need to configure the project to be extension less or use MVC wildcards for your documents ending with that extension such as "/NewsMVC/Detail/{id}.aspx".

In my example, I added the .aspx extension to my listing MVC alias to be "/NewsMVC/List.aspx", and defined the URL path of the document as "/NewsMVC/List" (.aspx will be added to the live URL automatically by the system):



If I then enable the web.config key, I get a proper Page view, because Routing and MVC has a higher priority in the system than standard URLs based on tree structure:



Note that since my MVC page is a very simple example, it doesn't provide any editing functionality, just a preview. The main goal achieved, however, was to get a proper view for the editor.

Because configuring a system like this is not the ideal way of doing things, we made some improvements to this in version 7.

Improvements to MVC in Kentico CMS v7

The extra configuration in v6 is in place because we needed to overcome regular page processing by standard engines with something more prioritized. That is why we decided to also build MVC support into our standard URLs and standard URL-rewriting engine. The following diagram describes the process of URL handling for virtual URLs provided by Kentico:



The URL pointing to the document in Kentico CMS can be shown in several ways (represented by violet colored items in the diagram). These ways are listed in order of their priority meaning that if a requested URL is matched, the system processes the request and no other subsequent URLs are considered for that request. Let me first explain their meanings:
  • MVC URL pattern and Routing URL patterns - Whether you define an MVC route in a URL path or as a document alias, it takes precedence in URL handling before other URL types. These two are handled by ASP.NET Routing engine. MVC is then handled by the MVC routing handler, while the Routing URL is handled by the default routing handler which then presents the content through regular page templates.
  • Standard URL path - The primary URL path of the document defined in its properties is the most prioritized of standard URLs. That is because language versions may have different URLs, and the system must display the correct language for that URL.
  • Alias path - An alias path, generated from location in the document tree, represents the default fallback path for the document. It is always available and guarantees that the document will be accessible from the live site by a specific friendly URL.
  • Wildcard URL path - Before we supported ASP.NET Routing, we had our own implementation of wildcard URLs which fortunately happens to have the very same syntax as Routing. Because this feature is implemented through database lookup, for performance reasons it is listed as the last option for document search by URL. The decision between using Routing (processed on server side by ASP.NET as a flat list of regular expressions) and our Wildcards (processed on SQL server through LIKE expression) depends on how many various route patterns you have. The fewer route patterns you have, the better the performance you can get by leveraging the ASP.NET Routing option.
  • Document aliases - If no document is matched for the incoming URL, the system attempts to search the URL path and our wildcards (the SQL ones) in document aliases as the last option. Similar to SQL wildcards, this lookup is more expensive than default, and that is why the primary URL of the document is always either the standard URL path or an alias (also because they don't contain variable parts). As previously mentioned, Routing and MVC even for document aliases, is handled at the very beginning, very efficiently, so you don't need to worry about registering them as document aliases - there is no hidden performance cost in that. In page processing, document aliases work the same way as standard URLs, being processed by page template.
What we had in version 6 are two independent sets of URLs, each pointing to a different target view group:
  • MVC Controller and view - Handled only by MVC aliases. The displayed context must be taken from the RouteData collection if you use MVC aliases, because CurrentDocument and CurrentPageInfo are populated by the document to which the alias belongs, because technically the system is displaying that document with some additional parameters.
  • Page templates - Of all types (Portal, ASPX, Mixed), handled by Routing, and the standard URLs that we had in earlier versions.
This was the reason for which we had to provide the "CMSUseLiveURLForEditing" hack - to get a proper editing view.

What we made possible in version 7 is the green part of the diagram, which interconnects those two models, making MVC support much simpler. There is now a new page template type "MVC" which allows rendering of pages provided through their standard URLs using ASP.NET MVC. This has two main effects:
  • If you use an MVC type template for the document, it also automatically displays with its MVC representation in editing modes. You no longer need the appSettings key. (But we have kept it in Site settings in Site manager, for those who already use it and in case it is required for other scenarios.)
  • You can basically develop a whole site using MVC without the need to add any wildcard URLs to the project, but instead just use default document URLs as defined by their document tree hierarchy. This also means that CurrentDocument and CurrentPageInfo are properly populated by the system.
As you can see, this change has made MVC support much more flexible, enabling not just conversion of existing sections to MVC but also full site development using MVC.

As a case in point, let me show you that very same example section in v7. First, here is the configuration of the same MVC page in v7:



You may notice that only the detail view remains as document alias. This is because I don't really need a special page for it, as it has a dynamic URL and I will be able to access the whole MVC News section from the main listing.

I have also configured the URL path to the static Route "/NewsMVC/List". I did that only to provide the extensionless look and feel without the need to configure the IIS. That is one of the advantages of Routing, it can serve extensionless URLs without extra configuration. Alternatively, I could have simply used the .aspx extension for my MVC Views to get the same result (in that case URLs would have .aspx extension).

This means we basically removed the link to the MVC list view. We will want to configure the document through the new option, so we will configure the MVC document to use a specific page template, and configure that template for MVC with the Controller "NewsMVC" and the Action (View) "List", similar to what we had in v6:





And that is all. The result is the same in editing view without the need to do any hacks or configure the system in any special way:



You may notice that the v7 engine is smarter and therefore has no editing components, so it doesn't offer the edit menu.

The point is that this time the request is routed through the green part of the diagram and processes the page through a page template using the MVC controller and view - something not possible in v6. The Release Candidate for v7 is coming in 2 weeks so you can try it out for yourselves. Learn more about it here: http://devnet.kentico.com/Blogs/Martin-Hejtmanek/June-2012/Kentico-CMS-v7-Release-Plan-Update.aspx

I am also planning to check out Razor support, which should likewise work without any problems as of v7, as ASP.NET 4.0 is compiled against MVC3. I will let you know about it through another blog post with an introduction to Kentico vs. Razor.

Should you have any further recommendations or feedback on our MVC support, please let us know.
Share this article on   LinkedIn Google+

Martin Hejtmanek

Hi, I am the CTO of Kentico and I will be constantly providing you the information about current development process and other interesting technical things you might want to know about Kentico.

Comments

Martin Hejtmanek commented on

Hi Mike,

We are doing these things as we get feedback. So far there was no feedback on components, because developers using MVC model usually preferred their own code and things done as simple as possible with as much control as possible (that is also one of the key aspects of MVC and unit testing ...).

We are also focusing more on unit testing but this is still in progress, but allowing this is one of our long term priorities. We should be able to provide way how to unit test code with CMS objects without the database dependencies in v7 final to some extend, and continue with the next versions.

If you could send us an e-mail with more details on what you expect to use out of the box and how, it would be great. We don't want to go to unexplored waters as Umbraco did so we prefer feedback first, then development approach with MVC.

Mike commented on

But surely once you have an MVC page, there is zero value in almoast everything that Kentico has to offer in terms of building pages out of components? I mean, every web part or widget is based on the web forms model.

I also wonder if you have been able to rewrite those parts of Kentico that are simply impossible to unit test. Because one thing that MVC developers like, is more SOLID code and using dependency injection to resolve e.g. a CMS context object.

Just curious!

PS. Feature-wise Kentico 7 looks like a solid release!

Les Girvan commented on

Hi Martin,

Just wanted to add my appreciation to your decision to push back the release of V7 for all the right reasons.

Having spent many months looking at CMS's systems to provide our integrated solution, and Umbraco was one of them, this kind of consideration is so important to ensure the future integrity and stability that we require.

This also further endorses my decision to go with Kentico some 4 years ago now, and looking forward to many more years working with Kentico