Posts Tagged 'mobile jQuery'

Improving Performance with Output Caching

I’ve been spending most of my spare time over the past few weeks refactoring the code for my site, cocktailsrus.com, in the Visual Studio 11 beta–partly to play with the new stuff, but mostly just to replace my original quick-and dirty back end with something more elegant. With the process pretty much complete, the new version of the site will be much more maintainable, as well as more performant and scalable. And I don’t know about you, but whenever I see those two words together, the first thing that leaps to my mind is “caching.”

Caching is a fantastic way of reducing the amount of data access on a website. Unfortunately, it can also be a fantastic way of tying yourself in knots and serving the wrong data to the wrong user. It is just too easy to serve stale data–especially when you transition from a single server to a web farm. So which type of caching to use, and how to avoid serving stale data?

ASP.NET offers two types of caching:  data caching and output caching. Data caching is managed programmatically. Output caching is managed via attributes (MVC) or page directives (Web forms).

Historically, I’ve preferred data caching. I’ve specialized in content management systems over the years, and it’s a very rare situation where a CMS delivers the same content to everyone. Data caching allows very fine-grained control. Unfortunately, it doesn’t play very well with Web farms–at least, not since Microsoft removed some of the core SQL Server technologies that allowed it to do so.

So, given that I want to be able to scale up to a Web farm, the question I asked myself was, Could output caching help my application?

The obvious candidate for output caching is the page that displays individual cocktails. These don’t change very often, and are amongst the most heavily trafficked on the site. Also, and most significantly, retrieving a cocktail from the database involves a complex SQL query with many table joins. (A cocktail has multiple ingredients, related cocktails, an author, etc.) The fewer such calls I make, the better.

On the face of it, caching the individual cocktails should be easy. Each one has a unique ID, so you should need to do is add an OutputCache directive, like this:

output cache directive

Looks easy, doesn’t it? Each time the method is called, the individual cocktail will be cached by its ID for 60 seconds.

Unfortunately, it really isn’t as simple as that. This caching will work–but it will deliver the same version of the output to everyone: mobile device users, AJAX users, non-AJAX users…. You get the picture. A user with JavaScript enabled will suddenly find that they are getting the full page rather than an AJAX payload, leading to pages within pages, like this:

page within page screengrab

So simple caching won’t do. We’re going to need to cache four different versions for each cocktail, specifically:

  1. Mobile with no AJAX
  2. Mobile with AJAX
  3. Standard with no AJAX
  4. Standard with AJAX

Unfortunately, there isn’t a querystring parameter that’s going to allow us to make that distinction, so it’s time for a custom parameter.

The first thing we have to do is override the GetVaryByCustomString() method in the global.asax. Here, we can use the request to filter our caching into the four different groups. The site uses jQuery, and jQuery AJAX requests use the “X-Requested-With” header, so we can use that to determine if this was an AJAX request. That’s half of the problem solved. We can then use the underlying infrastructure (or, perhaps, our own version of it) to find out if this request came from a mobile device.

GetVaryByCustomString code

We then assign this to the controller method and we should have something that caches multiple versions and returns the appropriate version from the cache:

VaryByCustom argument

Which is great… except that when we look at it in Firefox, we have the same old problem:

second page within page screengrab

The issue here is where the caching is happening. Output cache is a clever beast, and it’s automatically offloading the work to the client–which is a great idea, but means that if our client switches from AJAX to non-AJAX versions, we end up delivering the wrong item from cache.

Fortunately, there is a simple solution. The OutputCache attribute accepts a Location argument, which you can use to tell it to cache on the server rather than the client:

Corrected OutputCache attribute

So now I have a caching system that will work happily on a Web farm, significantly reduce data access and provide the appropriate custom view to the client.

Kevin Rattan

For related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

Building Web Applications with ASP.NET and AJAX

jQuery: A Comprehensive Hands-On Introduction

Improved Device Detection with ASP.NET

This is a follow up to my last post where I did a quick-and-dirty hack to get around the limitations of ASP.NET’s built-in isMobileDevice property.

At the end of that post, I said I was going to wait and see if Microsoft did a better job next time around before I went to the trouble of improving my solution. Well, it didn’t work out that way. You see, even if I hadn’t disliked leaving a quick-and-dirty fix in place, it turned out that there was another complication that meant I really needed to provide a proper solution.

The app uses Ajax extensively (and explicitly) in the non-mobile version in order to give a better user experience. It also uses Ajax implicitly in the mobile solution, as jQuery mobile automatically converts links and forms into Ajax calls unless you tell it not to do so. What I hadn’t taken into account in my quick-and-dirty approach was that I wasn’t just detecting mobile devices inside the view engine – I also needed to detect them in order to provide partial pages to Ajax calls in the non-mobile Web version.

The app delivers three kinds of content:

  • Full Web Pages
  • Full Mobile Pages
  • Partial pages for non-mobile Ajax calls

Unfortunately, as jQuery mobile also makes Ajax calls, when mobiles were not detected by the built-in isMobileDevice property, I was returning the partial page when I should have been returning the full mobile page.

So back to the drawing board.

And since I was now going to have to do things properly, I decided to support all the major mobile platforms, not just Android.

I created a new static method isMobileDevice() which accepts an argument of type HttpContextBase and checks both the built-in isMobileDevice property and series of string constants. I then call this method from inside the ViewEngine Nuget and also from my controllers when detecting if the call is an Ajax call.

Here is the key method:

Sample code from method detecting mobile devices

And here is one of the calls to the method:

Sample code calling the new method

If you want the full code, I’ve placed it online as devicedetector.txt. I hope you find it useful.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

Building Web Applications with ASP.NET and Ajax

Progressive Enhancement with ASP.NET MVC and jQuery Mobile

In an earlier post, I blogged about the NuGet that allows ASP.NET MVC3 to take the same approach as MVC4 to delivering different views for mobiles and standard browsers. I’ve now fully implemented this on my cocktails site, and come across some interesting complications when combining it with Ajax and progressive enhancement.

This is the mobile site:

mobile site screen shot

This is the standard version:

standard site screen shot

The site uses Ajax in a number of ways – some present no problem, but others are more challenging. Autocomplete functionality was easy to implement – I just used jQuery UI on on both the mobile and the standard site and returned the appropriate JSON data from an ActionResult.

c# returning JsonResult

The bigger challenge arose when I wanted to use Ajax more extensively in page navigation – and I ended up having to adopt two different solutions.

When working with ASP.NET MVC, my preferred approach for progressive enhancement is to place the main page content into partial pages. These are simply included inside normal views for the standard non-Ajax version of the site. Once that version is fully functional, I then add JavaScript to request those partial pages using the jQuery .load() method. In this case, that was a particularly attractive approach, as it meant that the mobile and standard versions only needed to be shells – almost all of the content would be inside partial views shared by both of them.

Normally, I would detect that a request is using Ajax, and if so return the partial view, otherwise return the full version. The trouble is, jQuery mobile uses Ajax extensively for page navigation – so the Ajax version intended for use with non-Mobile devices could end up being sent to the mobile site, where it would not work correctly.

The first solution I adopted was to return the partial view only if it was both using Ajax and a standard browser, like so….

C# returning partial view

This works pretty well – unless the request comes from a form and uses multipart data (e.g. uploading an image). I use the forms plugin to ‘ajaxify’ forms, and for some reason ASP.NET MVC does not pick up that the request is Ajax when it’s encoded for multipart data. I found various suggestions to deal with this online (e.g. passing in the iframe parameter), but none of them worked for me. So I switched to plan B – providing an alternative version of the method.

C# duplicate renamed method

Now all I had to do was write a little bit of JavaScript on the client to change the action method before making the Ajax submission:

javascript ajax call

The end result is online now as the beta version of the site. The standard version uses HTML5, jQuery 1.7 and Ajax navigation through progressive enhancement. The mobile version uses jQuery Mobile 1.0 and has a completely different UI, but the same underlying functionality. I’m really enjoying developing with jQuery Mobile – it really is an excellent new tool in the Web developer armory.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

jQuery: A Comprehensive Hands-On Introduction

More tips for ASP.NET MVC jQuery Mobile sites

I’ve had a very enjoyable week finalizing the alpha of my new ASP.NET MVC/jQuery Mobile site and putting it online at cocktails-r-us. I’m now testing and refining it (as well as dutifully drinking lots of cocktails so I can take photos and upload them to the site: all for the good of the application, you understand. Now, if I can just work out a way to claim them on expenses….). Along the way, I’ve come across a few problems (and solutions) that come from combining ASP.NET MVC with jQuery mobile and thought I’d share them with you.

One nice feature of jQuery mobile RC2 is that you can easily hide labels in a way that works with assistive technologies. This is achieved using a css class (“ui-hidden-accessible”). You can then use the HTML5 placeholder attribute to supply helpful text to your users. This allows you to make excellent use of the highly restricted space available in mobile devices.

This:

html code

Becomes this:

output using placeholder

This is great…. Except for the fact that the ASP.NET MVC LabelFor() helper, unlike other helpers, has no overload allowing you to add HTML attributes – so there’s no out-of-the-box way to add the class attribute without having to go back to hard-coded HTML. And so you end up with this…

output showing label

The result is that you end up hard-coding the HTML, when what you really want to do is something like this:

html helper code

Fortunately, the solution lies in something I’ve already blogged about. In earlier posts, I detailed how the MVC3 ActionLink helper allows you to add the hyphenated data-* HTML5 attributes using an underscore, and how you can create your own helper to do so in MVC2. Well, it turned out I also needed that code in MVC3 after all. The UrlHelper class does not apply the substitution – so when I used the UrlHelper in an ImageLink helper, I had to use the ‘MVC2′ approach. That turned out to be fortunate, as I was able to reuse that code in a helper that extended LabelFor() to accept an anonymous object for HTML attributes – and at the same time future proof it against the need to add any data-* attributes in the future. (I won’t post the code, as it’s too similar to a previous blog post, but I’ve put it online here for anyone who wants it.)

So then I ran the code and… didn’t get what I was hoping for. The LabelFor() helper worked as I’d intended… but EditorFor() was ignoring the placeholder attribute, leaving me with this:

textbox with no label or placeholder

Not very helpful, is it? The code does not throw an error, but the attribute doesn’t get added and there’s nothing in the UI to guide the user. There are a couple of complex fixes for this. You can create a template for EditorFor(), or you can create your own custom attributes. I chose to go down the easy route, and switch from the EditorFor() helper provided by the Visual Studio Entity Framework scaffolding, and use TextBoxFor() instead – which did respect the attributes and gave me the result I was looking for.

Here’s the code:

code with textboxfor

And here’s the output.

working output

So I suppose the message is – ASP.NET MVC and jQuery Mobile can play nicely together, but it’s early days yet and expect to do a lot of fiddling around to get the exact behavior you’re looking for.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

jQuery: A Comprehensive Hands-On Introduction

Preparing for ASP.NET MVC 4 Mobile Development

ASP.NET MVC 4 will include a neat little feature allowing you to create mobile views very easily. All you will have to do to mobile-enable a view is add ‘mobile’ to its name and then customize it for mobiles. How you customize it is up to you – but the built in Visual Studio MVC 4 templating will be using jQuery mobile (hurray!).

If you have a file called “index.cshtml”, you would copy it and create the new file “index.mobile.cshtml”. If you have “index.aspx” then you would create “index.mobile.aspx”. These then sit side-by-side with your standard views. Internally, ASP.NET MVC will detect that a mobile device is being used and direct the request to the appropriate view.

Sounds good, doesn’t it?

Wouldn’t it be nice if you could get a head start on developing your apps this way using the ASP.NET MVC3? Well, thanks to Scott Hanselman, you can. He’s created a NuGet that works the same way, and made it available for you to download and integrate into your projects. It includes both C# and VB code,

vb and csharp files

so after you’ve installed it, you need to go in and remove whichever you’re not using:

Csharp files

But once you’re done that, you have a mechanism for developing mobile apps in a forwards-compatible way. In the example below, I created a separate mobile master using jQuery mobile, which I then tied into the mobile version of the page using the Layout property:

code sample

Then I ran the application in Internet Explorer, and also in Firefox using the User Agent Switcher add on. The application automatically delivered the appropriate views:

Here is IE acting as a normal browser:

Web site

And here is Firefox pretending to be iPhone 3:

mobile web site

All in all, a useful little NuGet which sets you up for developing mobile apps in ASP.NET MVC 4.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

jQuery: A Comprehensive Hands-On Introduction

Scaffolding ASP.NET MVC 3 using Entity Framework 4

As I mentioned in an earlier post, my current project combines Entity Framework, ASP.NET MVC3 and jQuery mobile. It’s my first real mobile-device focused project, and I’m not too concerned about scalability at the moment (at least not on the first cut – I will probably refactor later). My main interest right now is in seeing how the different technologies fit together, but especially in getting some hands-on experience with the shiny new jQuery mobile framework. Along the way, though, I’ve used MVC3′s EF scaffolding for the first time – and have a few thoughts to share, along with a couple of gotchas.

I started out with a Model First Entity Framework project (see this article by Doug Rehnstrom if you’re not familiar with this approach). The real application has a separate data project and is moderately complex, but I’ve recreated a simplified bit of it here to illustrate the advantages/disadvantages of the approach.

Here is a (very simple) part of the EF model. There are two tables – one for beverages (e.g. Bourbon, Orange Juice) one for types of beverage (e.g. Spirits, Fruit Juice).

object model using EF

I used this model to create the database (as per Doug’s article), then tried to use it to scaffold the ASP.NET MVC application. I right-click on the controllers folder and select Add Controller.

(Minor) Gotcha Number 1: I get an error saying there are no model classes:

no model error message

So – first we need to do a build. Now we get our dialog with model classes. I fill out the dialog for a scaffolded BeverageTypeController, and tell it to use the cocktailsContainer as the data context (‘cocktails’ is the model/database name).

Add controller dialog

Now when I click Add, I get a controller complete with read/write methods. I also get matching Views:

Files in solution explorer

There are some serious pros and cons here. The biggest pro, of course, is how fast all this is. In no time at all, I’ve created an object model, a database and a whole set of controllers and scaffolded views. So – this is pretty RAD for ASP.NET MVC. And that, of course, is also the con. There is no proper separation of the layers. The controller contains all the data access code – definitely NOT what we teach you to do in Learning Tree’s ASP.NET MVC course, Building Web Applications with ASP.NET MVC.

But still, for my purposes on my current project, this lets me get up and running quickly so I can focus on the mobile part of the application. I can always refactor later on and create a proper n-tier application. There is, however, one remaining gotcha, and it’s a nasty one.

Gotcha Number 2: The scaffolding code causes problems with SelectLists.

The problem is that the scaffolding code uses the name of the selected property as the ViewBag key. This means, for example, that the list of BeverageTypes inside the Beverage page is held in the ViewBag.BeverageTypeId property. That’s a problem, because beverage.BeverageTypeId is defined as the selected item – and that upsets the dropdownlsit, which looks in a number of places for the selected item and gets confused if the key is the same as the property name.

code with beverageTypeId key

Unfortunately, this confusion ends up wiping the selected value, as the following illustration demonstrates (orange juice is obviously not a spirit!):

end result with error

The solution is to change the name of the ViewBag property in both the controller and the view:

Here’s the amended controller:

amended controller code

And here’s the amended view:

amended view code

And this time your selection will be respected:

corrected output

So, overall, the EF scaffolding is a very nice RAD feature. It has a couple of glitches, but it’s allowed me to get a LOT of work done very quickly. I wouldn’t use it for the final version of a project, but in this case it’s just what I need to test out the viability of my application design – I can always refactor it later on if I decide that my prototype looks promising.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

How to use HTML5 data-* in ASP.NET MVC 2

In my last post, I gave a couple of tips on working with ASP.NET MVC and HTML5. The only problem was, one of the tips – substituting underscores for hyphens in HTML5 data-* attributes – only works if you’ve upgraded to ASP.NET MVC 3. That got me thinking about the best way to handle data-* attributes in older versions of ASP.NET MVC.  As It turned out that was a really good thing to do, as I found I needed it when created an HtmlHelper that built links – so

Here’s the problem: attributes are supplied to the actionlink helper as properties of an anonymous object, and property names can’t contain hyphens.

The solution in ASP.NET MVC 3 is to substitute underscores, and the actionlink helper converts them to hyphens.

Here’s a solution for ASP.NET MVC 2: write an extension method to convert the _ in attributes to -.

I wrote an extension method for the HtmlHelper class that accepted text for the link, a routevalues object and an anonymous object to hold the HTML attributes. Note that the method is returning an MvcHtmlString rather than a string – otherwise, your HTML is encoded when it’s written into the page, leading to the HTML being displayed rather than interpreted:

signature of the extension method

Inside the method, I created a TagBuilder and started to build the <a> tag. Most of it is fairly straight-forward, e.g. using a UrlHelper to create the link:

using the UrlHelper

The difficulty comes when you have to work with the htmlAttributes anonymous object. It’s not a collection, so you can’t just enumerate through it. You have to use reflection instead. Here, I get the type, then the properties – then iterate through the properties and use a string.Replace() to generate the correct string name for the attribute. I then combine the corrected attribute string with the  value of the property:

using reflection with the anonymous object

All I have to do now is add the namespace to my page or web.config:

importing the namespace

And then I can call the method inside my view:

calling the new helper

Which gives me the same output as I get from the actionlink in ASP.NET MVC3:

the html output

the visual output

That’s it for now. More on developing with ASP.NET MVC3, EF4 and mobile jQuery soon!

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

jQuery: A Comprehensive Hands-On Introduction

HTML5: Next Generation Web Development

Tips for Using HTML5 with ASP.NET MVC

The mobile version of jQuery is due out in the next few weeks – it’s currently a release candidate – and I’m working on a project using it. I haven’t done much in the way of mobile development so far, as I’ve been kept permanently busy doing traditional Web development. However, the release of mobile jQuery, and the massive uptake of mobile devices, means it’s time to get with the program. I’m learning a lot as I go, and I’ll be sharing anything I think is useful or interesting with you as the project progresses.

The project combines jQuery mobile with HTML5, Entity Framework 4 and ASP.NET MVC3 (with Razor). I’m not using HTML5 on a whim, but because jQuery mobile relies on it – and that, in turn, made me turn automatically to ASP.NET MVC rather than ASP.NET Web Forms, as MVC lets you write all your own HTML. Having said which, there are some gotchas even with ASP.NET MVC – so here are a couple of tips to help you write HTML5 with ASP.NET MVC.

  1. Change Visual Studio’s default HTML validation.

    By default, Visual Studio validates your HTML as XHTML 1.0 Transitional. This will give you lots of annoying green underlining.

    error warning on data-role

    You can get rid of the warnings (and get useful HTML5 validation) by going into Tools > Options > Text Editor > HTML > Validation and changing the target to HTML5:

    data-role with no error warning

  2. Use _ for – in data-*

    ASP.NET MVC 3 allows you to pass in the hyphenated data-* HTML5 attributes using an underscore. It then automatically replaces the underscore with the hyphen. So that the following code

    use of _ in place of -

outputs this HTML:

output HTML from use of _ in place of -

which, when you’re using jQuery mobile on its default settings on a black footer, produces this rather elegant button:

visual output use of _ in place of -

And if you think that’s lacking in contrast, we can always add in another data-* element from jQuery mobile…

use of data-theme

which gives us…

output from use of data-theme

Of course, the _ for – substitution only works if you’re using ASP.NET MVC3 – which begs the question of what you can do if you’re still using ASP.NET MVC 2. It’s such an interesting question, I think I might just address in it in my next blog post….

Goodbye until then.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

jQuery: A Comprehensive Hands-On Introduction

HTML5: Next Generation Web Development


Learning Tree International

.NET & Visual Studio Courses

Learning Tree offers over 245 IT and Management courses, including a full curriculum of over 15 .NET training options.

Free White Papers

Questions on current IT or Management topics? Access our Complete Online Resource Library of over 65 White Papers, Articles and Podcasts

Enter your email address to subscribe to this blog and receive notifications of new posts by e-mail.

Join 9 other followers

Follow Learning Tree on Twitter

Archives

Do you need a customized .NET training solution delivered at your facility?

Last year Learning Tree held nearly 2,500 on-site training events worldwide. To find out more about hosting one at your location, click here for a free consultation.
Live, online training

Follow

Get every new post delivered to your Inbox.