Posts Tagged 'ASP.NET MVC'



Exposing IQueryable/oData Endpoints With Web API

This is a follow on from my post on Web API and the Entity Framework. In that post, I showed a couple of approaches to dealing with JSON serialization problems in the Visual Studio 11 beta. Now I want to look at returning IQueryable from Web API methods.

IQueryable allows you to do what it says on the box: return an object that can be queried from the client. In other words, you can pass through arguments that tell the server what data to retrieve. This is a hot topic on the Web, with some people strongly against the idea and some strongly for it. The argument is between convenience (look how easy it is to get any data I want!) and security/architecture (look how easy it is for someone else to get any data they want).

I don’t have strong views either way. I share the concerns of those who worry about leaving client layers free to bombard the data layer with inappropriate (and potentially dangerous) queries, but I also like the convenience of being able to shape my queries from the client—especially given the Web API’s (partial) support of the oData specification. (For those unfamiliar with oData, it allows you to use querystring arguments to modify the query at the server, e.g., $top=10 will become .Take(10) in the EF query).

If I don’t use IQuerable, I will need to write lots of different methods to allow for different queries (e.g., in cocktails-r-us, I need to search for cocktails by beverage, non-liquid ingredient, name, id, etc.). Here is a simple example from my demo project, with two methods:  one returning an IEnumerable of BeverageTypes, the other a single BeverageType by id:

original version of code

If I want to get an individual BeverageType, I make a get request along these lines: http://%5Bmysite%5D/api/beveragetype/2. Here is the Firebug output from such a request:

output from non-oData request

If I switch to IQueryable as the return type, however, I can supply both queries from a single method (note the addition of ‘AsQuerable()’ at the end of the method return):

IQueryable version of the code

Now I can write my oData query as “http://%5BMySite%5D/api/beveragetype?$filter=id eq 2“, so I no longer need my separate specialized method.

screenshot of oData request and result

Let’s try and simplify the method. The oData specification allows us to expand associations using $expand, so let’s remove the .Include(“Beverages”) call from our method and pass that through on the querystring as follows: http://%5BMySite%5D/api/beveragetype?$filter=id eq 2&$expand=Beverages.

Here is the new code:

code without include

And here is the result… not quite what we were hoping for:

result of $expand - no include

It turns out that the Web API does not support $expand…. And I rather hope it never does. If Web API supported $expand, then my users would be able to create huge queries with far too many joins. In cocktails-r-us, I only want to return all the details of a cocktail (ingredients, comments, ratings, related cocktails, etc.) for one cocktail at a time. I don’t want users to be able to join all those tables in one massive query. So, that’s the upside. The downside is that I have to go back to using multiple methods, but even then I should only need two:  one to get a specific cocktail (or, in this case, BeverageType) by ID, the other to return lists of them by whatever criteria the client prefers.

final version of two methods

Since I can deal with security concerns by forcing my clients to authenticate (and only giving access to trusted developers in the first place), and that leaves me with only one concern: will my client developers write ill-advised queries? They might, for example return too many rows at once instead of paginating through the data as I would prefer. Fortunately, there is a solution: the [ResultLimit(n)] attribute. This restricts the number of items returned. So now our remote users will have to page through the data rather than return it all at once.

ResultLimit attribute

If we examine the output in Firefox/Firebug, you can see that only 5 rows are returned even though the query requested all the rows:

output with limit in place

ResultLimit is not a perfect solution. It only restricts the number of items returned from the method, not the number retrieved from the database. Here is what’s happening on the server:

Results on server

However, since the remote user won’t be able to get the data they want the easy way, they will be forced to write oData pagination queries like “http://%5Bsite%5D/api/beveragetype?$skip=5&$top=5&$orderby=Type desc” which would give them the following output on the client:

oData paginated query

I understand why people are nervous about exposing IQueryable, and I wouldn’t do it in a completely open way where anyone’s code can access my data without authentication, but I love its openness and flexibility and the way it works so easily with Web API.

Kevin Rattan

For related information, check out this course from Learning Tree: Building Web Applications with ASP.NET MVC.

Working With the Entity Framework and the Web API

In my last post, I talked about the new Web API controllers in MVC and showed how they work with simple data. In the real world, of course, I want them to work with my existing data, which uses Entity Framework. It turns out that this is far from straightforward (at least, in the beta).

Let’s start by trying to expose some standard EF data. When I began coding my personal website www.cocktailsrus.com I used model-first rather than code-first development. (At that point, my focus was on getting to know jQuery mobile, and I was not concerned with best practices in MVC; I have refactored it since). So let’s go back to basics and begin with an .edmx version of the simple data I used in my last post.

beverageType in designer

The code to return this object using Entity Framework and Web API is as follows (with the result first placed into a  variable  so I can more easily examine the return in the debugger):

code to return IEnumerable of BeverageType

When we try and access this in Internet Explorer, we get the following error message:

“The type ‘BeverageType’ cannot be serialized to JSON because its IsReference setting is ‘True’. The JSON format does not support references because there is no standardized format for representing references. To enable serialization, disable the IsReference setting on the type or an appropriate parent class of the type.”

Interestingly, if we use Firefox, it actually works–but here the response is formatted as XML. Still, that suggests we’re almost there. Let’s make it more interesting. Let’s add an Association to our .edmx file to make it more realistic.

design view of association

And let’s add an Include to our Entity Framework code so that we return the Association along with our object:

code with include

Strangely, we get exactly the same results as before. Internet Explorer gives the same JSON error message. Firefox returns the same XML, without the association. Perhaps turning off LazyLoading will improve the Firefox return?

code removing lazy loading

Sadly, it makes no difference. We get exactly the same error, and since there is no convenient way to change the IsReference setting in an .edmx, perhaps it’s time to switch to Code First Generation and see if we can’t return JSON properly to Internet Explorer.

Here are my types:

code first types

And here is my DbContext:

code first dbcontext

Let’s run it again and see what happens now… And yes–this time, we’ve managed to break both Internet Explorer and Firefox! Both get the following error message:

“You must write an attribute ‘type’=’object’ after writing the attribute with local name ‘__type’. ”

Now, this error is actually useful. It tells us we need to turn off proxy generation, so let’s tweak our DbContext. And we may as well turn of lazy loading here while we’re at it:

turning off proxy creation

Now the Web API makes a valiant effort, sends through the beginning of a JSON version of the data to both IE and Firefox, and then gives up with an error message:

screen capture error

Here is the error message:

“System.Runtime.Serialization.SerializationException: Object graph for type ‘Beverage’ contains cycles and cannot be serialized if reference tracking is disabled.”

At this point, I imagine we’re all starting to get a little frustrated. I know I am. So, to cut a long story (and a lot of Web searching) short… it looks like the fundamental problem lies in the interaction between the Entity Framework and the DataContractSerializer used in the beta. This is supposed to be fixed by a change to the JSON.Net serializer when Web API goes live – but in the meantime, what to do?

There are two possible approaches (and I’ve placed the code for both online here):

  1. Substitute the JSON.Net serializer in place of the default. For this, you need first to follow the helpful instructions in this blog post: http://blogs.msdn.com/b/henrikn/archive/2012/02/18/using-json-net-with-asp-net-web-api.aspx and then
    1. Add an instruction to the serializer to ignore self-referencing loops
    2. Add the new serializer in the Global.asax
  2. Use projection. The suggestions online seem to fall into two camps:
    1. Use projection with anonymous objects.
    2. Use projection with Data Transfer Objects.

But if I did want to use projection, why would I want to:

  1. return anonymous objects when I have perfectly good POCO objects, or
  2. create new DTOs when I already have perfectly good POCO objects?

So I wondered what would happen if I used projection with the same POCO Code First objects that the serializer had choked on when I returned them directly…

projection using code first poco objects

And here is the result in Firefox/Firebug:

output from projection

And in Internet Explorer/F12 Developer Tools

output in IE:

The Web API is going to be great, but it takes a little work if you’re using the beta. If you want to look at the code for either solution I outlined above, it’s available here. (The full project is 13MB, even as a zip, so I just put up the code: if you want it to run, you’ll need to copy the files into a VS11 project and download the various Nugets, as well as getting EF to generate the database for you).

In my next article, I’m going to take a look at the thorny issue of whether to return an IQueryable and—if you do choose to do so—how you can protect yourself against over-large queries.

Kevin Rattan

For related information, check out this course from Learning Tree:  Building Web Applications with ASP.NET MVC.

Building RESTful Services with Web API

One of the features I’ve most been looking forward to in the Visual Studio 11 beta is the Web API. It’s been my long-term goal to build an iPhone app to supplement my jQuery mobile view for my personal website, www.cocktailsrus.com (once I learn Objective-C), and a RESTful API is just what I need. In this post, I’m going to explain what the Web API is and how you can use it. In subsequent posts, I’ll look at the issues with combining Web API controllers with Entity Framework data, and the thorny issue of whether to expose oData/IQueryable endpoints. There’s a lot of ground to cover, so let’s get started.

What is the Web API?

The Web API is a new feature of the latest release of ASP.NET MVC. It adds a new controller base type, ApiController, which allows you to return JSON data directly from RESTful urls. (It was always possible to return JSON from Controllers by using the Json() method, but ApiControllers don’t return views, just serialized data. We can also easily expose oData endpoints: more on that in a later post.)

The Add Controller wizard now has new options:

The controller wizard

When you select an empty API controller with read/write actions, you get a basic stubbed template as a starting point:

The empty controller

There are a couple of changes I need to make at the outset:

  1. I want to return a list of BeverageTypes (spirits, non-alcoholic, wine, etc.) rather than a string array,
  2. I already have a BeverageTypeController as part of my MVC application, so I need to change the namespace from the default (in this case, Cocktails.Controllers) to Cocktails.Controllers.API to avoid a name collision.

Here is part of the changed class with a little sample data for testing purposes:

Method returning IEnumerable

Now I can make the following RESTful query “http://%5Bsite%5D/api/BeverageType” and get back JSON data:

Output from the RESTful call

The controller also stubbed out another method for me that accepted an id argument. With a little refactoring to move my data into a separate method – BeverageTypes() – I can now write code like this:

Get with an argument

Now I can make a RESTful query with an argument, thus – “http://%5Bsite%5D/api/BeverageType/1“:

output from the call

So, it looks like I have a nice, simple way of exposing my data as a RESTful API from within an ASP.NET MVC application. I should be able to consume my data from new clients and/or allow third parties to integrate with my site. Unfortunately, it turns out that once you add the Entity Framework into the mix, things get a whole lot more complicated – and that’s going to be the topic of my next post.

Kevin Rattan

For related courses, check out Building Web Applications with ASP.NET MVC from Learning Tree.

Streamlined Web Loading in the Visual Studio 11 Beta

One of the features of Visual Studio 11 that I’m really looking forward to taking advantage of is CSS and JavaScript minification and bundling.

As developers, we like to be able to break our applications into reusable components. That makes development and maintenance much more manageable. Sometimes, however, it can have an impact on performance. The more CSS style sheets and JavaScript files you add to a page, the longer that page will take to download – and it’s not just a matter of the size of the files; the number itself is a problem. Http requests are expensive; the more you have, the slower your page is to load, even if the absolute size of the downloaded files is not very large.

Visual Studio 11 comes with two new features that make it more practical to break our JavaScript and CSS into multiple file. Bundling and minification give us a means of ‘componentizing’ our Web applications, without taking the performance hit of too many http requests. Bundling allows you to combine multiple files into a single larger file. Minification removes unnecessary white spaces to ensure that the new file is as small as possible. Taken together, the two techniques have a major impact on performance.

There are two versions of the functionality: the simple, automatic way; and the much more useful custom approach. In the simple version, the contents of folders are automatically bundled and minified if your <link> and <script> tags to point at the default directories and don’t specify individual files, thus:

<link href=”/Content/css” rel=”stylesheet” type=”text/css” />

That gets converted into html along these lines at runtime:

<link rel=”stylesheet” type=”text/css” href=“/Content/themes/base/css?v= UM624qf1uFt8dYtiIV9PCmYhsyeewBIwY4Ob0i8OdW81” />

That’s fine as far as it goes, but is also rather limiting. You have to use default locations, and there’s no scope for having different bundles for different versions of your application. In my www.cocktailsrus.com site, I have two distinct versions, for mobile and standard browsers, each of which requires different .css and .js files, so I need to be able to create custom bundles.

The MVC4 template comes with a feature that’s designed to support this – ResolveBundleUrl():

<link href=”@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl (“~/Content/css”) rel=”stylesheet” type=”text/css” />

Now we can define our own custom bundles. In my case, I can create two new sub-folders under the style and script paths, one for mobiles and one for the standard Web site:

Then I change the paths passed to ResolveBundleUrl() to point at my new folders….

<link href=”@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl(“~/Content/site/css”) rel=”stylesheet” type=”text/css” />

<script src=”@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl(“~/Scripts/site/js”)“></script>

and… it doesn’t work.

Although ResolveBundleUrl() supports adding non-default paths, you have to do a little more work and register your new paths in the application start event in the Global.asax before it can use those paths.

code in the global asax adding bundles

This tells the system that we’re adding two bundles – one for .css files and one for .js, and that all the files in the specified directories should be part of the bundle. (You can also specify individual files if you need to control the loading order beyond the default settings, which first prioritize known libraries like jQuery, then load the files alphabetically).

One nice additional feature is that the bundles are cached on the browser using the generated path (e.g. css?v=UM624qf1uFt8dYtiIV9PCmYhsyeewBIwY4Ob0i8OdW81). This means that not only are they loaded faster the first time the user visits the site, they do not need to be downloaded again the next time. More significantly, if any of the files in the bundled folder changes, so does the generated path. That means your users will never be stuck with old versions of your style sheets or JavaScript files.

Kevin Rattan

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

Building Web Applications with ASP.NET and Ajax

Building Web Applications with ASP.NET MVC

How to Use ViewModels Without Sacrificing Encapsulation

I have been using ASP.NET MVC extensively over the past year, and the more I use it, the more I like it. However, there remain a couple of things that bug me. One is the fact that the built-in validation doesn’t work with repeating forms. The other is the “best practice” of placing Data Annotations on a ViewModel class.

For me, validation rules belong on the business object itself, not on the ViewModel. One of the key benefits of encapsulation is that we reduce code duplication. If we don’t encapsulate the validation rules inside the object, then we are doomed to repeat them once for every presentation layer. Data Annotations in an MVC ViewModel are not available to a WPF UI. Not only does this lead to redundancy, it increases the risk of inconsistencies cropping up between UI.

So no problem, you might think. All we have to do is add the Data Annotations to the Model itself, and then add the Model as a property of the ViewModel.

Okay, let’s try that.

Here is the Model:

BasicClass simple C# class

And here is the ViewModel:

The ViewModel class

This looks straightforward enough. But look at what happens when we ask Visual Studio to scaffold the View:

View scaffolding

What happened to our “Basic” Model property? It’s not there. The scaffolding only seems to work for simple properties.

Okay, so let’s add the details of the Model to the View. In fact, let’s cheat. We’ll get Visual Studio to scaffold the inner Model for us. First we’ll create a throwaway View. Then we copy the contents of the form and paste it into the View that’s typed to the ViewModel. All we have to do then is change the lambda expressions to point at model.Basic rather than just model:

Full scaffolding

Problem solved. The View now contains the data we need and also respects our data annotations…

This means we can pass the ViewModel through to a Controller method and pick up the Model we need via the ViewModel’s “Basic” property. There’s only one problem:  How do we use the UpdateModel() method when we’re only interested in a property on the object passed to the method, rather than the whole object? Fortunately, Microsoft anticipated the need and there’s an overload on UpdateModel() that allows us to specify a prefix. In this case, not surprisingly, the HTML helpers have inserted the prefix “Basic”:

UpdateModel() with second argument

As you can see, the Model has successfully been bound, so we now have a mechanism for taking advantage of ViewModels without sacrificing encapsulation.

Kevin Rattan

For related information, check out Building Web Applications with ASP.NET MVC from Learning Tree.

Retrieving Data with a JavaScript MVC Framework

This is part of series of posts on building reliable, testable Ajax-enabled applications using a JavaScript MVC framework. In my first post, I discussed why this was a key technology and set up my initial server-side resources in an ASP.NET MVC application. The second post created the test framework for the application, using QUnit for the client-side code and Visual Studio for the server-side code. My last post started to provide the pay-off for all that work: integrating the client-side ViewModel’s data and methods with HTML.

The point of this application is to have the user select a customer from a dropdown list and display the information for that customer, retrieved from the server. Using Knockout as a framework for implementing the MVVM pattern, I’ve created a client-side Customer ViewModel written in JavaScript that exposes three properties (CustId, CompanyName, and City) and the functions to retrieve a Customer (getCustomer) and delete a Customer (deleteCustomer). I’ve also wired up the properties to controls on the page.

But I’ve left out one important part: integrating the code that actually retrieves the data from the server into events in the page. In this post, I’ll take care of two topics: adding a dropdownlist that displays all the customers in the Northwind database and retrieving the appropriate customer object from my server when the user selects a customer from the list. Unlike my previous posts, however, I’ll defer showing the TDD code that proves the code works to the end of the post.

Creating the DropDown List

My first step is to define the dropdown list. In my client-side ViewModel I need a property that will expose the list of Customer objects that I retrieve. I add that to the list of properties that I defined in my ViewModel again using one of Knockout’s functions. Because I’m working with multiple objects, I use Knockout’s observableArray function:

this.Customers = ko.observableArray();

Technically speaking, I probably don’t need to use observableArray here. The observableArray function gives me two-way databinding: changes to the Customers property will be reflected in the page and changes to the array in the page would be reflected in the property. Right now, I don’t intend to let the user add or remove Customers from this property so using observableArray is probably providing more functionality than I need. However, the syntax for updating “observable” properties is different from updating a standard variable: I’m using observableArray here because it makes my life easier to use Knockout’s observable functions on all of my ViewModel’s properties instead of just some of them.

Also on the client, I need a function that uses jQuery’s getJson method to retrieve the customer objects that will populate the property. I add the following function to my client-side Customer ViewModel to do that. In the function, I use my controller variable to build the URL that retrieves the list of Customer objects from the right controller. Once I’ve retrieved the array, I update my Customers property with it:

this.getCustomers = function () {
         $.getJSON("/" + Controller + "/GetAllCustomers",
				null,
				function (custs) {
                        self.Customers(custs);
                    }
                 );
    };

With the client-side code created, I need the server-side method in my controller that returns the JSON objects that will populate the dropdownlist. Rather than return the whole Customer object, I’ll create an anonymous object that holds just the values the dropdownlist needs—CustomerId and CompanyName:

public ActionResult GetAllCustomers()
{
  using (northwndEntities ne = new northwndEntities())
  {
    var res = from c in ne.Customers
	select new  {cName = c.CompanyName, cId = c.CustomerID};
    return this.Json(res.ToArray(), JsonRequestBehavior.AllowGet);
   };
}

My final step in displaying these customers is to bind a dropdownlist on the page and bind it to the Customers property I’ve created on my ViewModel. That markup looks like this:

<select data-bind="options: Customers, 
                    optionsText: 'cName', 
                    optionsValue: 'cId', 
                    optionsCaption: 'Select a  Customer'">
</select>

I’m using several of Knockout’s bindings here to tie the list to the property:

  • options: this binding is passed the name of the property on my ViewModel that holds the list of objects to be used to populate the dropdown list.
  • optionsText/optionsValue: These bindings specify which property on the object are to be used for the text and value attributes in the list. The text attribute specifies the property to be displayed to the user while the value property specifies the property to be passed to any related function
  • optionsCaption: Specifies the value to be displayed in the list when it’s first displayed

I don’t need the selectedOptions binding that lets you specify the list’s current selected value through a property on the ViewModel.

Retrieving the Customer Object

Now I need a client-side method to retrieve the customer object from the server. I write that method so that it accepts a customer Id and updates the ViewModel’s properties with the retrieved data:

this.getCustomer = function (custId) {
        $.getJSON("/" + Controller + "/CustomerById/" + custId,
		null,
		function (cust) {
                self.CustId(cust.CustomerID);
                self.CompanyName(cust.CompanyName);
                self.City(cust.City);
        }
       );
    };

I can’t however, wire this method up to my dropdown list directly. Here’s the syntax that ties the list to a function called fetchCustomer on my ViewModel that runs as soon as the user selects an item in the list:

<select data-bind="event: {change: fetchCustomer}, 
                   options: Customers, …

I’m using Knockout’s event binding which lets me specify an event (change, in this case) to a method (fetchCustomer). Unfortunately, there’s no provision in this binding to pass a parameter to the fetchCustomer function. However, when a function is called through Knockout’s binding process, the function is passed two parameters. The second paremeter includes information about the event and through that parameter’s target property I can access the element that fired the event. From there it’s just a short step to retrieving the current value on the element that invoked the function through its value property.

This code gets the currently selected value from the dropdownlist that calls the function and passes that value to my getCustomer function:

this.fetchCustomer = function (ignore, event) 
    {
      this.getCustomer(event.target.value);
    };

Which raises the question of why have the fetchCustomer method at all? Why not call the getCustomer function from the dropdownlist binding and just extract the selected value from the second parameter? I don’t know that I have a good answer for that question. I’m could say that I’m trying to create a testable ViewModel and the more functions that I have that are tied to my View, the harder it is to test the ViewModel. However, a test for a method like fetchCustomer isn’t hard to construct—this code would do the trick:

var eventTest = { target: { value: "ALFKI"} };
cust.fetchCustomer(null, eventTest);

Still, I’m happier isolating any code that seems to me is related to the user interface into its own methods so I’ll continue with this design.

As I said at the start of this series, Learning Tree has several excellent courses in this area. In Canada, I teach both Learning Tree’s ASP.NET MVC course (which has a chapter on TDD in ASP.NET MVC) and its Design Patterns and Best Practices course (which goes into TDD in more depth). But Learning Tree also has related courses that I don’t get to teach, including ones on JavaScript and jQuery.

There’s lots more I could do here. With Knockout it’s easy to enable and disable portions of your page by binding them to properties on your ViewModel. I also haven’t tried to create or manage multiple objects on the page. However, I have convinced myself (and, hopefully, you) that there’s at least one MVC/MVVM framework out there that lets you create applications in a testable, reliable way even when your application includes client-side code.

Test Code

And here’s the code that I used to test my code. First, the test for client-side code that returns the list of customers:

test("Get All Customers",
                  function () {
                  stop();
                  cust = new Customer("Test");
                  cust.getCustomers();
                  setTimeout(function () 
                            {
                             equals(cust.Customers().length, 2, 
                                        "All customers not retrieved");
                             start();
                            },
                        3000);
                  }
    );

Now the mock server-side method that I used to with that client-side test code:

public ActionResult GetAllCustomers()
{
  List<Customer> custs = new List<Customer>();
  Customer cust = Customer.CreateCustomer("PHVIS", 
              "PH&V Information Services", null);
  cust.City = "Regina";
  custs.Add(cust);
  cust = Customer.CreateCustomer("Other", "Other one", null);
  cust.City = "Winnipeg";
  custs.Add(cust);
  return this.Json(custs.ToArray(), JsonRequestBehavior.AllowGet);
}

Finally, the test code for the production version of the server-side method:

[TestMethod]
public void GetAllCustomersTest()
{
  HomeController hc = new HomeController();
  System.Web.Mvc.JsonResult jres = 
                (System.Web.Mvc.JsonResult) hc.GetAllCustomers();
  dynamic res = jres.Data;
  Assert.AreEqual(96, res.Length, "Unable to retrieve all customers");
}

Creating a Testable Client-side ViewModel with Knockout

In my previous post, I discussed why I a JavaScript MVC or MVVM framework is essential: It lets you prove, quickly and conveniently, that your code works so that you can assemble applications out of reliable components. In that post I also started on a project to show how one of those frameworks—Knockout—supports the MVVM design pattern. I also created the server-side methods that my application (an ASP.NET View that displays information for a customer selected by the user) would need. However, what I created were mock functions that I could use for testing. In this post, I’ll start to create the client-side resources my application would need while still focussing on testing the code.

Setting Up the Client

My first step on the client (after adding the Knockout library to my Scripts folder, of course) is to add the necessary script references to my layout page to support using Knockout. For testing purposes, I also include a RenderSection that will allow me to selectively add script references on a View-by-View basis. This basic set of references is used by every View:

<head> <meta charset="utf-8" />  
 <title>@ViewBag.Title</title> 
 <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />  
 <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>  
 <script src="@Url.Content("~/Scripts/knockout-2.0.0.js")" type="text/javascript"></script>
 @RenderSection("Header",false) 
</head> 

With those references in place I’m ready to start generating some client-side code. First, I add a Javascript file to my Scripts folder to hold the Customer ViewModel that I’ll developer. Again, to support testing, I add a variable called controller to the file that will let me redirect my server-side requests to my mock methods:

var controller = ""; 

Now I can (finally) start defining my ViewModel, beginning with the properties that hold the data my page will both display and allow users to update. I define those properties using Knockout’s observable function:

var Customer = function (custIdIn) { 
 this.CustId = ko.observable(); 
 this.CompanyName = ko.observable(); 
 this.City = ko.observable(); 

Using the observable function gives me two-way databinding (the ViewModel automatically updates the View’s elements, the View’s elements automatically update the ViewModel). Other Knockout functions support handling arrays and computed values. I don’t have to use the observable function—if I only wanted the data to flow from my Customer ViewModel to the elements on my page, I could skip using the observable function.

I also define a variable to refer to the current value of this (my ViewModel). I’ll need a reference to my ViewModel later and defining self at this point in the ViewModel’s code bypasses any of the ways that this gets redefined:

var self = this; 

My next step is, still in my Customer ViewModel, to define a function that uses jQuery’s getJSON method to retrieve data from my server-side methods. I’m going to call this function getCustomer and have it retrieve the Customer object from my server-side methods. Once the JSON object is retrieved, the code updates my ViewModel’s properties from the JSON object’s properties. This is one of the places that I use the self variable I defined earlier to avoid problems with this being redefined. I also use my controller variable to define the URL used to access the service:

this.getCustomer = function (custId) {
  $.getJSON("/" + controller + "/CustomerById/" + custId, 
 null, 
 function (cust) { 
 self.CustId(cust.CustomerID); 
 self.CompanyName(cust.CompanyName); 
 self.City(cust.City); } ); }; 

Because my CustId, CompanyName, and City properties are really Knockout observable functions, I must use the syntax shown here to update their values. This ensures, for instance, that changes to the CompanyName and City properties will automatically be reflected in any elements in my page that the properties are databound to.

Testing a JavaScript ViewModel

I’ve got enough functionality written at this point to begin testing (too much, actually, for a real TDD approach—I should have started writing my tests before I put any code in my getCustomer function). In my last post, I defined a controller (TestController) and an action method (CustomerViewModelTest) to use for testing. I can now create the View that will be called from that action method (CustomerViewModelTest.cshtml). I use QUnit for testing client-side code, so I need to add the files Qunit needs (a JavaScript file and a CSS file) to my application. However, I’d prefer not to download those files on every page so I don’t add those references my layout View. Instead, in my test View, I add the references to the Header section that my Layout View references. I also add a reference to the JavaScript file holding my Customer ViewModel that I want to test:

@{ ViewBag.Title = "Customer ViewModel Tests"; } 
@section Header { 
 <script src="@Url.Content("~/Scripts/CustomerVieModel.js")" type="text/javascript"></script>  
 <link href="@Url.Content("~/Content/Tests/qunit.css")" rel="stylesheet" type="text/css" />  
 <script src="@Url.Content("~/Scripts/qunit.js")" type="text/javascript"></script>  
} 

In the body of my page, I add in the headers that QUnit needs to execute and display test results:

<form action="/Test/index">
 <h1 id="qunit-header">Customer MVVM Tests</h1>
 <h1 id="qunit-bannder"></h1>
 <div id="qunit-testrunner-toolbar"></div>
 <h2 id="qunit-userAgent"></h2>
 <ol id="qunit-tests"></ol>
</form> 

I can now test my ViewModel using QUnit’s test function. I set my controller variable to direct all my getJson requests to the mock methods on my Test controller. I use jQuery to prevent my tests from running until the page is fully loaded:

controller = "Test"; $(function () { 

That test consists of instantiating my Customer ViewModel, calling its getCustomer method passing a customer Id, and checking to see if the ViewModel’s properties were updated correctly. Since I’m making an asynchronous server-side call, I can’t simply call my getCustomer method and check the property results—my test code might run faster than my server-side call and check the property before the result is returned. To get around that, I use QUnit’s asyncTest and JavaScript’s setTimeout functions to wait for one second before checking the result using QUnit’s equals function:

var cust; test("Get Customer", 
 function () { 
 stop(); 
 cust = new Customer("Test"); 
 cust.getCustomer("ALFKI"); 
 setTimeout( function () { 
 equals(cust.City(), "Regina", "Customer not retrieved"); 
 start(); }, 
 3000); } ); 

I can now run my tests and see the results by calling my CustomerViewModel action method on my TestController (and, of course, my test passes the first time).

At this point I have a testable ViewModel but, of course, that’s not much good unless it supports a real page. That’s what I’m going to look at in my next post. But with this framework in place, I know that I’m building my page with something that works.

If you’re looking for a course with a good introduction to TDD in Visual Studio, Learning Tree’s Design Patterns and Best Practices in .NET course is a good choice. However, Learning Tree’s ASP.NET MVC course devotes a whole chapter to TDD with ASP.NET MVC.

Peter Vogel

Fun With NuGet

I was teaching an ASP.NET MVC class just before Christmas, and was forcefully reminded of two things – 1) ASP.NET MVC Routing can be really tricky to get your head around, and 2) a surprising number of people still aren’t familiar with NuGets and don’t take advantage of them.

So this blog post is designed to kill two birds with one stone. I’m going to introduce NuGets and show you one in particular that helps you become familiar with the routing engine.

First up: what is NuGet?

NuGet is a mechanism to make the downloading and installing of useful .NET libraries transparent and easy. It comes with Visual Studio – but you may have an old version and need to uninstall it and install the latest version before you begin. Once you’ve done so, it’s very easy to install new packages. Here’s how you do it…

1. Open a project to which you want to add a NuGet (in this case, the routing debugger).

2. Go to Tools | Library Package Manager | Manage NuGet Packages

Screenshot of Menu

3. That brings up the NuGet dialog.

NuGet Dialog

4. You then search for the NuGet you’re after (in this case, the route debugger by Phil Haacked) and then click on the Install button once you’ve found it.

searching for NuGet Package

5. Now all you have to do is use it. In this case, that means running your application and using the useful debugging utility to see which of your routes matches the address in the browser. A great way to learn more about routes and test whether your routes really do what you think they’re doing….  (I’d advise using this one on a learn-routing project rather than a real site, by the way).

Route Debugger in action

NuGets – they’re easy to use, and there’s one out there that’s just what you need.

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

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

Detecting Mobile Devices with ASP.NET MVC

In a recent post I talked about the NuGet that allows you to do MVC4-style mobile views in MVC3. My cocktailsrus.com beta site is now live and in the process of testing, and I’ve found an issue with the NuGet (or, more accurately, with the underlying ASP.NET property it relies on). I thought it would be a good idea to share the problem – and my solution – with you.

The problem is that the ASP.NET isMobileDevice property is detects some mobile devices, but by no means all. So when I checked my site in an iPhone, I got the mobile version. When I checked it using Android, I got the full version – not what I wanted at all. I came across this problem in MVC, but because it’s an underlying ASP.NET problem, it would apply to Web Forms in exactly the same way.

Here is how the NuGet determines which view to return:

original NuGet Code

As you can see, the constructor passes through a predicate which uses the isMobileDevice property. The methods that do the work of returning the appropriate view to the appropriate device use this predicate. Which is great…. Unless the property is not being set correctly. Unfortunately, that’s exactly what happens with Android (and other) mobile devices. ASP.NET doesn’t recognize them, so neither does the NuGet.

My solution is definitely on the quick and dirty side. I only really care about supporting iPhones and Androids. With other mobile devices, I’m willing to take pot luck on isMobileDevice detecting them correctly. So all I needed to do was find out if the device was either recognized as a mobile device, or was an Android device.

Here is my amended version of the NuGet, which adds a second test to the predicate, checking whether the the UserAgent contains the word “Android”:

amended nuget code

I tested it, and received the correct version on both iPhone and Android devices – so it’s solved my problem. The next step is to tidy it up and use a constant instead of a string literal. And, of course, to wait and see if the next version of ASP.NET does a better job of detecting mobile devices. If not, then I’ll have to work up a more fully featured fix (like looking into updating the underlying definition files ASP.NET is using to determine what is a mobile device, or at least checking the UserAgent contains “palm”, “blackberry” etc.).

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


Learning Tree International

.NET & Visual Studio Courses

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

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 29 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

%d bloggers like this: