Resources Over MVC - A More Complex Sample

November 6, 2011 01:22 by Admin

The previous Bare Minimum posts showed how to use the Resources Over MVC (ROM) assembly to add some RESTful features to a web site developed using ASP.Net MVC. This post introduces a second sample project that will be used in future posts to demonstrates the other functionality available within ROM.

Creating the Sample

The sample web service was inspired by Scott Gu’s recent post on building an ASP.Net MVC 3 site using the Entity Framework. First a new ASP.NET MVC 3 Web Application project was created. After selecting the project template in the Add New Project wizard, you are shown the New ASP.NET MVC 3 Project dialog and given a choice of sub template. For this sample I went with the “Internet Application” template as it gives us a head start on the views. However, before proceeding I did the following:

  • Changed the main header to “My MVC Web Service”
  • Deleted the AccountController and associated Model and Views
  • Removed all the authentication, membership, profile and role configuration from the web.config
  • Removed the _LogOnPartial.cshtml control and its usage within _Layout.cshtml
  • Deleted the About action on the HomeController, its associated View and menu tab
  • Made a minor tweak to the CSS to bring the header properly into view

You may wonder why I started with an Internet Application then stripped most of it away. Why didn’t I just start with an Empty project? Well, one of the representations we will create is XHTML. Having the standard layout / master page will make our web service far more usable for a developer exploring it within their browser and it is easier to take functionality away than to add it!

First we’ll add three classes to the Model folder. These are the classes we will expose to the User Agents (i.e. the clients) that want to use our web service:

public class Product
{
     public string Uri { get; set; }
     public int Id { get; set; }
     public string Name { get; set; }
     public int CategoryId { get; set; }
     public Decimal? UnitPrice { get; set; }
     public int UnitsInStock { get; set; }
     public Category Category { get; set; }
}
 
public class Category
{
     public string Uri { get; set; }
     public int CategoryId { get; set; }
     public string Name { get; set; }
     [XmlIgnore, ScriptIgnore]
     public virtual List<Product> Products { get; set; }
}
 
public class Resource
{
     public string Uri { get; set; }
     public string FriendlyName { get; set; }
     public string Id { get; set; }
}

We’ll start by exposing a “Home Page.” This resource will be accessed through a well known URI and from it User Agents can discover all other URIs. Use the Add wizard to create three empty controllers called HomeController, CategoryController and ProductController. Next add Home, Category and Product folders under the Views directory. Then use the Add View wizard to scaffold a basic view called Index in each of the new folders (selecting the appropriate Model class and using the List template):

CreateView

If we fill in the HomeController’s Index action with code to populate a list of resources we will have a working web site:

var resources = new List<Resource>
                     {
                         new Resource
                            {
                                 FriendlyName = "Categories",
                                 Id = "categories",
                                 Uri = Url.Action("Index", "Categories", null, 
                                                  Request.Url.Scheme, string.Empty)
                             },
                         new Resource
                            {
                                 FriendlyName = "Products",
                                 Id = "products",
                                 Uri = Url.Action("Index", "Products", null,
                                 Request.Url.Scheme, string.Empty)
                             }
                     };

 

Browsing to the home page of the web service will give a very basic view of the list of resources. However, with the use of appropriate tags, we can have a response which can be viewed in a browser by a developer exploring the web service and can also easily be parsed by a User Agent to locate the URIs of the Products and Categories resources:

<!DOCTYPE html>
<html>
<head>
    <title>Home</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <div id="header">
            <div id="title">
                <h1>My MVC Web Service</h1>
            </div>
            <div id="menucontainer">
                <ul id="menu">
                    <li><a href="/">Home</a></li>
                </ul>
            </div>
        </div>
        <div id="main">
<h2>Home</h2>
<div class="home">
    <ul class="resources">
        <li class="categories">
            <a href='http://localhost:3160/Categories'>Categories</a>
        </li>
        <li class="products">
            <a href='http://localhost:3160/Products'>Products</a>
        </li>
    </ul>
</div>
        </div>
        <div id="footer">
        </div>
    </div>
</body>
</html>

 

By instantiating Category and Product objects through whatever mechanism you choose (in our simple case creating them out of thin air and attaching to a singleton to represent a database) and some simple formatting in the Index pages, we end up with a basic web service that works... and we are just using an out of the box ASP.Net MVC project.

However, one of the objectives of our web service is to allow the User Agent to ask for different “representations” (i.e. different formats) of each resource (e.g. XML or JSON). For this we need to make use of the ROM assembly.

Support Multiple Representations

As described in the Bare Minimum Part 1 and Bare Minimum Part 2 posts, the ROM assembly can be used to add support for serving and receiving multiple representations. In the Bare Minimum sample we did that at  Controller / Action level. In this sample I have done this at a global level by:

  • Adding a reference to the ROM assembly to the project (you can do this through NuGet)

 

  • Registering the MultipleRepresentationsAttribute Action Filter as a default filter in the Application_Start method in Global.asax:
                    filters.Add(new MultipleRepresentationsAttribute());
    
    
    

     

    • Register the MultipleRepresentationsBinder as the default model binder for the entire web service. You do this by using the following in the Application_Start method in Global.asax:
             ModelBinders.Binders.DefaultBinder = (new MultipleRepresentationsBinder());
    
    
    

     

    Now you have a web service that provides the basics at a global level. The second sample included in the source code download started at this point but now contains more features. The following posts will describe each of those features, such as a help representation, overloading POST, supporting less functional User Agents etc. You can download the sample project in a standalone solution here:

    Samples.WebService.zip (4.39 mb)

    The next few blogs will explain more of the features the ROM assembly will support.


    Add comment

      Country flag

    biuquote
    • Comment
    • Preview
    Loading