ASP.NET MVC 4 Mobile Features

I read about mvc 4 and decided to try out some of the new cool mobile features, so I went ahead and installed it, it installs side-by-side with mvc 3 so that’s nice. It comes with a new mobile application project template that uses jquery mobile which looks pretty good but since I want to build a web application for both desktop and mobile devices I’m going to start off from the internet application project template.

The default template uses CSS media queries which is an extension to CSS for media types, it allows you to override the default css rules for different agents. CSS rules defined inside

@media only screen and (max-width: 850px) {

will be applied if the browser window is 850 pixels wide or less. That combined with the viewport meta tag

<meta name="viewport" content="width=device-width">

makes the default project template render pretty nice in both desktop and mobile browsers as seen below.

aspnetmvc4_mobile_responsive

So what should I do if that isn’t enough? I want to completely customize the views for mobile agents but still use the same controllers. This is easily done! MVC4 introduces a mechanism to override views, layouts and partial views by naming conventions. For instance to get a mobile specific index page I simply add Index.Mobile.cshtml, same goes for the layout i.e. Shared\_Layout.Mobile.cshtml.

Having that said, let’s customize the mobile views, for that I’d like to use the jQuery mobile library that works on all the major mobile browsers. Installing the jQuery.Mobile.MVC NuGet package will get us on our way.

PM> Install-Package jQuery.Mobile.MVC

The package will setup the scripts and reference them and create a _Layout.Mobile.cshtml which links in the jquery mobile css, I needed to manually change the referenced jQuery version in _Layout.cshtml from 1.6.3 (default) to 1.6.4. A neat detail with this package is that a view switcher controller is added which enables us to easily switch between the desktop and mobile version.

I created the corresponding mobile views in /Home and threw in the following code into _Layout.Mobile.cshtml

<ul data-role="listview"&gt;
	<li data-role="list-divider">Navigation</li>
	<li>@Html.ActionLink("Home", "Index", "Home")</li>
	<li>@Html.ActionLink("About", "About", "Home")</li>
	<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

and simple as that I now had a mobile customized site.

aspnetmvc4_mobile_custom_mobile

Doesn’t get much easier than that!

Code available here (4,4MB), haven’t done much though! ;-)

/A

 

What about WCF 4.5 and the async/await pattern?

From what I’ve heard it should be pretty smooth to produce asynchronous server/client code with .net 4.5, so let’s try it out! Defining async methods on the service contract is now a lot cleaner :

[ServiceContract]
public interface IPeopleService
{
	[OperationContract]
	Task<IList<Person>> GetPeople();
}

instead of the wcf 4.0 way which would look something like this :

[ServiceContract]
public interface IPeopleService
{
	[OperationContract(AsyncPattern=true)]
	IAsyncResult BeginGetPeople(AsyncCallback cb, object state);

	[OperationContract]
	IList<Person> GetPeople();

	[OperationContract]
	IList<Person> EndGetPeople(IAsyncResult ar);
}

the server side implementation of the operation when returning a task is straightforward :

public async Task<IList<Person>> GetPeople()
{
	Task t1 = Task.Delay(500);
	Task t2 = Task.Delay(500);
	await Task.WhenAll(t1, t2);

	return await Task.Factory.StartNew(() => people);
}

If you don’t want to await something in the method you can skip the async keyword and still return a Task as shown below, async on a method simply tells the compiler that “I’m going to await something in this method”.

public Task<IList<Person>> GetPeople()
{
	return Task.FromResult(people);
}

Anyways it’s really nice to skip the non-implemented begin/end methods on the server which was simply boiler plating in .net 4.0. For the sake of simplicity the service will be hosted in a console application and for consuming the service I’ve implemented a simple proxy that inherits ClientBase<TChannel> and implements the contract. See the code if this confuses you (which probably means that you’re a noob ;-)). The client code when working with tasks is clean and straightforward as well :

var serviceProxy = new PeopleServiceProxy("PeopleServiceEndpoint");

Task<IList<Person>> people = serviceProxy.GetPeople();
people.ContinueWith(
	x =>
		{
			foreach (Person person in x.Result)
			{
				Console.WriteLine(
					"{0} {1} born {2}",
					person.FirstName,
					person.LastName,
					person.BirthDate.ToShortDateString());
			}
		});

We can control on which thread we will continue by passing in a TaskScheduler. So far so good, so what about testing? I’m using Nunit which integrates really well with VS when using resharper. I want to write an integration test (not unit) to make sure everything works well including the WCF part since unit testing my simple service is too easy ;-) I’ll host the service in the Setup method and take it down in the teardown. A simple test then looks like :

[Test]
public void ShallBeAbleToGetDateTimeFromService()
{
	IPeopleService serviceProxy = new PeopleServiceProxy("PeopleServiceEndpoint");

	Task<IList<Person>> getPeopleTask = serviceProxy.GetPeople();
	getPeopleTask.Wait();

	IList<Person> result = getPeopleTask.Result;

	Assert.IsNotNull(result);
	Assert.AreEqual(2, result.Count);

	(serviceProxy as IDisposable).Dispose();
}

Obviously we’d use facades to call on services in a real application but the principle is the same. It doesn’t get much cleaner than this imo.

/A

Get the code here! (67KB)