Using jQuery Mobile in an ASP.NET MVC 4 and SignalR Application

Posted by: Sumit Maitra , on 3/14/2012, in Category ASP.NET MVC
Views: 141675
Abstract: The recently released ASP.NET MVC 4 beta has enhanced mobile support through the introduction of new APIs and out of box support for jQuery Mobile. In this article, we will explore how jQuery.Mobile.MVC package, that is a part of MVC4, leverages jQuery.mobile and HTML5 to create targeted views for each device

The recently released ASP.NET MVC 4 beta has enhanced mobile support through the introduction of new APIs and out of box support for jQuery Mobile. The Mobile web project template helps you develop targeted mobile web applications ground up.

MVC 4 also has a new 'View Switching' functionality that helps adding Mobile capabilities to an existing site in a very clean way. In this article, we will see how we can take an existing MVC 4 application that is built for the desktop browser only and add mobile views to it.

Download the non-mobile site's code from here and follow along to make it mobile enabled.

 

Starting off

If we run the code now in a mobile browser, we will see the following Home page. As we can see, this is just a 're-arranged' version of the desktop site. The following meta tag (in _Layout.cshtml) helps scale things to the smaller view port of the mobile device.

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

initial-index-page-iphone-wp7

If we navigate to the 'Review' or 'Edit' pages, we will see due to the styles applied to the text area, the mobile views are warped. WP7 (Mango) emulator's IE and an iPhone's Safari render the 'Review' page as follows. Thus, dynamic views using CSS can only go so far.

initial-review-page-iphone-wp7

 

Bringing in jQuery Mobile

Nuget has two packages for jQuery mobile

  • jQuery.mobile - Pulls in only the jQuery Mobile js and css dependencies.

  • jQuery.Mobile.MVC - Pulls in all jQuery.mobile and MVC4 goodies like adding the ViewSwitcherController, adding the _Layout.mobile.cshtml

Through the Package Manager Console let's install jQuery.Mobile.MVC. The following dependencies should get installed.

install-jquery-mobile-mvc-from-nuget

 

Patching a minor gotcha

Once you install jQuery mobile, since all the JavaScript's get downloaded in the Scripts folder due to the bundling and minification setup by default (in _layout.cshtml), the jquery.mobile behavior will kick in for certain components like buttons and text boxes in non-mobile sites too.

update-web-config-for-mobile-dependencies

To fix this, we simply create a Mobile folder under Scripts folder and move the mobile related js into it.

mobile-dependencies-solution-explorer

Similarly for Content folder, create a mobile sub-folder and move the mobile related classes in it. Also copy the Content/images into Content/mobile/images.

mobile-content-solution-explorer

Now open the _Layout.mobile.cshtml and change the references to point to the correct 'mobile' folder.

image

Getting the View Switcher in Action

With the mobile references in place, let's run the app and refresh our Mobile view. We will see a slightly different view. The original CSS has been stripped and we have a little heading that tells us that currently the Mobile View is being shown and we could toggle back to 'Desktop View' if we wanted. However rest of the page is pretty messed up.

display-view-switcher-wp7

Clicking on Desktop view at this point will throw an error saying ViewSwitcher controller not found. This is not the fault of MVC. It's our code that bombed. Remember we have a custom controller factory that creates Controllers as required. We have not added the ViewSwitcher controller in the BlogControllerFactory class.

add-view-switcher-to-controller-factory

With that piece of code in place, we can now switch between Desktop and Mobile views, except that the mobile view looks tad worse than the Desktop view.

Adding Mobile specific Views

To introduce specific mobile views that are custom made for mobile screens, MVC4 allows you to add views with a custom display mode by appending '.displaymode' to a view. We take advantage of this by adding Index.mobile view for the Index page. The '.mobile' display mode comes by default with the jQuery.Mobile.MVC package. Later we will see how we can target different mobile browsers differently.

We use the standard MVC scaffold tooling to generate a 'List' type view for our BlogPost model class.

add-mobile-index-view

Now when we view the application instead of the modified desktop view, we get a custom Mobile view.

mobile-index-view-wp7

If you click on the 'Desktop View', you will see the original desktop view which is also available at the same URL on your desktop browser.

Recap

Let's do a quick recap here, because what we've got here is the crux of mobile support in MVC.

  • We added jQuery.Mobile.MVC from Nuget

  • We added a custom view with a .mobile appended to the View's name

And just like that we now can have two different views for the exact same Action or URL.

Under the Covers

The MVC4 infrastructure has under the covers done quite a bit of work for us here. There is a new DisplayModeProvider that by default ships with two modes, desktop and mobile. For desktop it checks browser agent information to see if the browser is on a mobile device or desktop device. To pick up the mobile view it checks if a corresponding .mobile view exists and if it does, uses that view.

Unless you want to add your custom views the DisplayModeProvider stays out of the picture. We will see a sample of how to use DisplayModeProvider a little later. For now let's deep dive into jQuery mobile techniques to make our mobile views more attractive.

Enabling switching from Desktop to Mobile view on Desktop Browser

Now if you visit the application from the desktop browser you will not see a switch to mobile view link because no one really wants to see the mobile view on a desktop browser. But it is an awfully handy thing to do when debugging. To enable the view switcher in Desktop browser, open _ViewSwitcher.cshtml and in the first line’s if(…) condition, remove ‘Request.Browser.IsMobileDevice &&’. If we remove this we will see the view switcher in desktop browser as well.

Using jQuery.mobile

Since mobile views usually have lesser screen-space showing a table/grid layout isn't usually an effective presentation layout. Instead, we keep things at a minimal and try to get users to navigate in small steps.

For our home screen instead of showing Details, Edit, Review, Delete for each row we let user navigate to a 'Details' page where there will be additional controls to do the Edit, Review and Delete. The markup for the Index.mobile.cshtml is thus reduced to the following.

index-mobile-markup

Understanding the Markup

- The '@section header'

The '@section header' markup encapsulates a section that is designated as the 'header' tag in HTML5.

- <h1>@ViewBag.Title</h1>

Shows the title of the page.

- <div data-role="button" data-icon="plus" class="ui-btn-right">

This is the line where we first encounter jquery mobile custom attributes. Here 'data-role' is an attribute that indicates to jQuery how the content in the container should be rendered. 'data-icon' is an attribute that defines the icon to use on the button. The various types of icons are defined here. Through all our walkthrough we will see various custom attributes that add meta information that helps jquery render the UI.

The section in this div gets rendered as a button to the right of the header.

- <div data-role="content">

This section indicates to jQuery.mobile that this div is the container for content

- <ul data-role="listview">

The data-role="listview" indicates that jquery should apply special rendering for the list.

- <li data-role="list-divider">Current Posts</li>

The first list time has the data-role of a list-divider. This makes the list item un-clickable and it gives it different visual cues.

- Using razor sytax we add the rest of the posts. To keep things short, we only show the post.Title property.

Now when we browse to the Index page on a mobile browser the page looks as follows

new-mobile-index-view-wp7

As we see above this is a standard and easy on eyes view that provides a clean way to invoke the 'Create' action (header button) and the 'Details' action (list item). Next we create a Details.mobile.cshtml to create the mobile view.

Adding a Mobile Details View

When the user clicks or taps on the list items we take them to a details page where they see the entire post and can do Edit/Delete/Review if required.

We start off with a standard MVC view called Details.mobile.cshtml

We then modify the markup to give it a 'mobile' look.

The final markup looks as follows:

details-mobile-markup

- The header section has the data_icon attribute set to arrow-l (arrow left) and the data_rel attribute set to back. This means the button will mimic the browser back button and also the button is to the left of the header.

- The content section is standard

- I have used a List view here though we don't really have a list, I just used the list-divider rendering to give the post title a different look from the post content.

- <pre style="white-space: pre-line">

This tag encapsulates the post content while maintaining the linefeeds.

- Button Rendering

We have three buttons for three different actions. Each with a built-in icon.

The final UI looks as follows on a mobile browser

details-mobile-wp7

Now arguably that's not the best mobile UI by far, however we get an idea of how jQuery mobile helps us build a Mobile specific page.

Using similar markup we create the Review, Edit and Delete pages and when done they looks as follows:

edit-mobile-wp7

delete-mobile-wp7

Adding a view specifically for a Device

So far we have seen how we can add views that simply go by whether the browser is on a Mobile or Desktop device. What if we want to handle different devices separately; For example target WP7 separate from iOS? This is where we get DisplayModeProvider in the play.

We have to register a new DisplayMode in the Global.asax. To register the mode we have to give it a name and provide a condition that will help determine the device that we are targeting.

Let us say we want to add a special mode for iPhones only. The following code registers the new display mode

register-iphone-display-mode

We are providing a lambda expression that checks the HttpContext's User Agent for the term iPhone, through do a case insensitive search. If the condition is satisfied the DisplayProvider will look for a view that ends with iphone.cshtml. Note we are inserting it at position 0 of all the modes so, this condition is evaluated first. If this condition fails the generic 'mobile' view kicks in which falls through to the generic view.

Adding an iPhone View

Just to test it out, we will add a Index view for the iphone that has two lines per list instead of the one line per list we have here.

Add a new Index view with the name Index.iphone.cshtml. The following markup adds two lines for each Post in the application.

iphone-index-view

There is nothing new from a markup perspective except that for each line item has two lines, one wrapped as header and another as a paragraph.

When we publish this code, it looks as follows on the iPhone:

iphone-screen-index

The same page on Windows Phone (emulator) looks as follows

wp7-screen-index

The same page on IE9 looks as follows

ie9-screen-index

To see the app in action, visit the application from different devices at http://apps.sumitmaitra.com/funwithsignalr/

The best part is SignalR works across ALL these browsers. Isn't that cool?

Conclusion

We saw how we can use jQuery.Mobile.MVC package, that is a part of MVC4, leverages jQuery.mobile and HTML5 to create targeted views for each device. Best part is the routing is transparent so all devices are actually looking at the same URL.

We should use mobile views because

  1. It helps us tailor views to specific devices

  2. It helps reduce bandwidth usage over mobile devices by giving us option to remove un-necessary graphics from Mobile views.

  3. Gives us the ability to build UI much closer to native mobile devices in look and behavior.

The only major ‘con’ of this approach is initial increase in effort for new views, however this is mostly mitigated in the long run because maintaining separate views usually means lesser ‘cross-platform’ hacks hence cleaner and easier to maintain markup.

With ASP.NET MVC 4, we are really looking at a very powerful framework that enables you to develop rich web applications for any target device (and audience).

The entire source code of this article can be downloaded over here

Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Sumit is a .NET consultant and has been working on Microsoft Technologies since his college days. He edits, he codes and he manages content when at work. C# is his first love, but he is often seen flirting with Java and Objective C. You can follow him on twitter at @sumitkm or email him at sumitkm [at] gmail


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by dotcore on Thursday, March 22, 2012 8:16 PM
@sumitmaitr have you checked the jqmvc extensions on codeplex. when would i need these extensions in an app you just demonstrated?

ps. i am a huge fan of your articles. keep them coming!
Comment posted by Micle on Saturday, March 24, 2012 1:31 PM
Great Article

I found one directory submission website for .net technology only http://www.dotnettechy.com/dotnet-directory-submit-website.aspx

here we can get relevant backlinks
Comment posted by Dotnet Techy on Sunday, April 22, 2012 5:37 AM
Great Article :)

We can also submit our .net related links on http://www.dotnettechy.com to improve traffic.

The dotnettechy.com is a community of .Net developers joined together to learn, to teach, to find solutions, to find interview questions and answers, to find .net website / blog collection and to have fun programming.
Comment posted by David Woodfin on Monday, April 30, 2012 1:13 PM
Hi,
Thank you for your nice information.I like it.
Comment posted by Matt C on Tuesday, May 1, 2012 4:17 AM
This is real good stuff. Another reason why I plan on moving to MVC in my next project
Comment posted by Sumit on Tuesday, May 1, 2012 9:40 AM
David and Matt glad you enjoyed the post. Yes, ASP.NET MVC is a rocking platform!
Comment posted by Noob on Thursday, July 5, 2012 6:36 PM
Maybe I'm missing something (which is possible, since I'm new to all this stuff), but where is the SignalR part of this post?  The title of the post indicates that SignalR is used, but I can't see where or how.  I see SignalR-related stuff in the download, but I was hoping for an explanation of how to use it, when to use, why, etc.
Comment posted by Sumit on Friday, July 6, 2012 12:10 AM
Hello Noob,
We should have made that more obvious. The SignalR part hasn't changed from our original SignalR article at http://www.dotnetcurry.com/ShowArticle.aspx?ID=780. In fact the 'beginning code' is code from the above article. We'll add a link back to the SignalR article.

Sorry for the confusion.
Thanks and Regards,
Sumit.
Comment posted by Mor on Tuesday, August 7, 2012 7:28 AM
hello,
very nice article.
i am sorry but i tried to run this app
but i have a problem with the EntityFramework ConnectionString.
i think that its missing the db FunWithSignalR  ?
Comment posted by Sumit on Wednesday, August 8, 2012 3:05 PM
Hello Mor,
The application uses Entity Framework Code first. So it will generate the DB if it can't find it. All you have to do is make sure the connection string is pointing to a SQL Server instance where you have permission to create a database. The connection string in the code points to .\SQLEXPRESSR2 Please modify the web.config and replace the .\SQLEXPRESSR2 with your SQL SErver instance. Default is .\SQLEXPRESS

Hope this Helps,
Sumit.
Comment posted by Alex on Monday, September 3, 2012 9:41 PM
Hi, I have a problem with connectionstring too.
I tried to run it in VS2010 with default SQLEXPRESS with this connection string:
<add name="FunWithSignalR" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI; Initial Catalog=FunWithSignalR" providerName="System.Data.SqlClient" />

Then I tried to run it with VS2012 with SQL Express 2012, but without any result. Сan someone specify the correct connection string for my configuration? or please give me a link with your existing base from 'App_Data' so I can attach it to my sql 2012 sql server developer throw management studio.
Thanks!
Comment posted by Alex on Monday, September 3, 2012 11:15 PM
Now i've created FunWithSignalR database from founded on github sql query and now its connected.
But I still can't run code from FunWithSignalRSolution_MobileMVC_Final.zip, because there is TypeInitializationException in BlogPostContext.cs (rows 13, 14):

public BlogPostContext(string connectionName, string schemaName)          : base(connectionName)

Please, help )
Comment posted by Sumit on Tuesday, September 4, 2012 6:15 PM
Hi Alex,

In CompositionRoot.cs can you change line number 32 to
string connectionName = ConfigurationManager.ConnectionStrings["FunWithSignalR"].Name;

I am assuming your ConnectionString still has the name "FunWithSignalR".
Let me know if it works.

Thanks and Regards,
Sumit.
Comment posted by Sumit on Tuesday, September 4, 2012 6:32 PM
Additionally, if you don't have the database you can change the Database initializiation strategy from null to CreateDatabaseIfNoExists (line 21, BlogPostContext.cs) as follows:

Database.SetInitializer<BlogPostContext>(new System.Data.Entity.CreateDatabaseIfNotExists<BlogPostContext>());
Comment posted by anil babu on Thursday, December 13, 2012 3:17 AM
Give me examples on Jquery mobile using asp.net MVC
I am new this one

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel