Using Areas in Umbraco 5 to replace /base
In Umbraco 4 there is something called "/base" that is mostly used to easily output some XML without having to create a document type, template and content item.
This evening, Warren Buckley put me to work when he asked what I would use in the upcoming Umbraco 5 as a substitute for /base, for example to submit form values with AJAX (well.. AJAJ for JSON) and have some code performed on the values provided.
Luckily, MVC3 knows how to handle JSON data really well, so I put it to work for me a little bit.
In asp.net MVC, you would create a controller to accept JSON data and could even return it as well. In MVC, there's a concept called Areas. Areas are an easy way to group controllers, and Umbraco 5 is using them as well.
You can use my Jupiter as Visual Studio Solution to be able to open an Umbraco install in VS2010. In the Areas section, right-click on Areas and choose "Add.." > "Area". In my case, I named it "base", very original.
You get a few folders: Models, Views & Controllers. It's almost as if they're letting you know you're working with MVC huh?
To make things interesting I've made a tiny little Model (typically, the model does something with data) to be able to receive the posted form. I will be accepting a contact form with the fields Name, Email and Comment.
So on Models, right-click and create a new class, looking like this:
using System;
namespace Umbraco.Web.Areas.Base.Models
{
public class ContactModel
{
public String Name { get; set; }
public String Email { get; set; }
public String Comment { get; set; }
}
}
Next, right-click on Controllers and choose "Add controller..." and name it (very originally HelloWorldController). That will give you a simple blank controller. Now, I know I'm going to be posting data to it later, so I have added the HttpPost data annotation on the Index ActionResult.
Here is the simple controller:
using System.Web.Mvc;
using Umbraco.Web.Areas.Base.Models;
namespace Umbraco.Web.Areas.Base.Controllers
{
public class HelloWorldController : Controller
{
[HttpPost]
public ActionResult Index(ContactModel contact)
{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return Content(serializer.Serialize(contact));
}
}
}
All this does is accept something that looks like a contact (in our case: a JSON object with the properties Name, Email and Comment, more on that in the next code sample) and return it as a JSON object.
Update: Of course, as Matt points out, you don't even have to do the serialization yourself, you could also just return a JsonResult instead of a generic ActionResult:
public class HelloWorldController : Controller
{
[HttpPost]
public JsonResult Index(ContactModel contact)
{
return Json(contact);
}
}
After building the code I can do something like this in jQuery on one of my normal content pages:
$(function () {
$.ajax({
type: "POST",
url: "/base/HelloWorld",
data: JSON.stringify({ name: "John", email: "john@doe.com", comment: "testing" }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
alert("Name: " + data.Name + " | Email: " + data.Email + " | Comment: " + data.Comment);
}
});
});
This code was largely taken from the post by Phil Haack about this very subject: Sending JSON to an ASP.NET MVC Action Method Argument (yes Aaron, I did just use alert...).
As you can see, we are POSTing some JSON.stringify'd object to /base/HelloWorld (remember, we have an Area called "base" and a controller called "HelloWorld").
The controller accepts a ContactModel from the post, this model has a Name, Email and Comment property, which is what we're sending to the controller in the post variables. Quick note: Index is the default action, but if we wanted to be precise, we should change the url to "/base/HelloWorld/Index" instead.
This will result in a beatiful pop-up showing us what we've posted.

Of course, we COULD just do something in the controller with the posted data... like send an actual e-mail or something like that, but I'll leave it up to you, dear reader, to be creative.
This is not the only way to replace /base, it's still possible to use Razor (the basics are similar in v5) or you could also use a custom controller, which is very similar to using a controller in an Area.
Hey Seb,
Nice article, as usual =)
Just wondered if you had looked into using JsonResult as your actions return type rather than serializing the return model yourself? as the JsonResult should just do that for you.
Keep up the good work.
Matt
D'oh, I forgot about that one, thanks Matt, added to the post!
Don't we have to Register Area in MVC? How to do that in umbraco 5?
This is all you have to do, both in Umbraco and MVC.
You Do need to register Area.
When you create an Area, VS will create some default code to do this on file xxxxAreaRegistration.cs
Indeed, I meant to say: But VS will do this automatically for you, so the above is all you need to do.
Thanks for the correction though. :-)
Thanks Sebastian.
I abandoned /base some time ago and started using sciptable webservices which is kind of super nice.
You get alle the json serialization for free, you got session and complex datatypes.
Should I change horses?
best
jesper
Yeah, they are nice as well!
I can't say I've used them much, and it might not be possible to use them in MVC, I just don't know. :-)
Is the VS route configuration compatible with umbraco? In RC3 I get 404's for the routes.
Not sure what you mean. If you create an Area, you get a YourAreaNameRegistration class in which you can configure routes for the area YourAreaName.
So for anything under yoursite.ext/yourareaname you can create the routing any way you want.
I understand that as of RC3, the default global.asax routing is also pluggable, so you could insert your own routing code in there somehow as well (don't ask me how though).
So for your example VS creates a BaseAreaRegistration with Base/{controller}/{action}/{id} as the route, so this should route the urls yourdomain/Base/HelloWorld to your Index Action, but with RC3 (Haven't tried the other versions yet) It just gives 404's.
Thanks for the info on adding plugging into the global.asax I try to find out how.
Hmm, just tested with a fresh copy of RC3 and all I can say is: works on my machine. :-)
Thanks Sebastiaan, I'm Baffled.
Make sure the project is set up to be MVC3 to add Areas on a right click.
I had the change the ProjectTypeGuids in the csproj file.
The MVC3 guids are here:
http://bit.ly/HGbPVj
I've added an area and registered a route. I get the Umbraco install view when calling /base/home in the browser...
Any ideas?