A Match Made in Http Heaven - ASP.NET Web Forms and WebAPI

by ASP.NET AJAX Team | Comments 11

With the introduction of MVC 4 Microsoft has created a fantastic new way for developers to expose data via HTTP service.  WebAPI is extremely easy to configure when compared to WCF services, and can send content in a multitude of formats.  On top of that you can easily extend it at almost any level.  While WebAPI shipped with MVC 4, it can easily be used in Asp.Net AJAX as well!  In this blog we will take a look at setting up WebAPI in ASP.Net Web Forms

Before We Get Started

To follow along with this blog you will need to download and install MVC 4 Beta.  You can get the bits here. Once you run the installer, you are all set to continue on. :)

One Step Setup

The first thing we need to do is create a new project.  For this example I used a standard ASP.NET AJAX project template.

image 

With the project created, it's time to add a few references.  In the solution explorer, right click on the References folder and select Add Reference.

Add the following references:

System.Web.Http.dll
System.Web.Http.Common.dll
System.Web.Http.WebHost.dll

The project is now setup to work with WebAPI. That was much easier than configuring a WCF service, wasn’t it? :)

Now it’s time to get down to business!

WebAPI is based on routes, which are almost identical to MVC routes.  That means we need to configure routes which will be used to access the ApiControllers in our application.

To do this, open the global.asax in your project, and enter the following basic route in the Application_Start method:

RouteTable.Routes.MapHttpRoute( 
                   name: "DefaultApi", 
                   routeTemplate: "api/{controller}/{id}", 
                   defaults: new { id = System.Web.Http.RouteParameter.Optional } );

Note: To keep visual studio from yelling at you, and to make the project compile, you will need to add using statements for: System.Web.Http, and System.Web.Routing.

If you have worked with ASP.NET MVC, this route should look very familiar.  Basically, this route says: when a request comes in that starts with ‘/api’, send it to {controller}, and if there is an id in the url, go ahead and pass it along too. 

With the route set up, we need to add a controller to handle the specified route! 

In the solution explorer right click on the asp.net project, and select Add > New Folder, and name the new folder Api.  Next right click on the new folder, and select Add New Item

In the Add New Item dialog, select Web API controller, give the controller a name, and click Add.

image

Now we need to create an entity to expose through the service.  In this example I created a very simple Customer entity:

 
public class Customer
{
 public int Id { get; set; }
 public string FirstName { get; set; }
 public string LastName { get; set; }
}
 

Note: Make sure the object you want to expose has a parameter-less constructor! Otherwise there will be serialization issues.

The last thing we need to do in the controller, is make a new action method to return an IQueryable<Customer> as shown here:

// GET /api/<controller>
public IQueryable<Customer> Get()
{
 return repository.Get();
}

In the Get Customer method I am simply returning a Queryable list of Customers.  When you expose the entity set as IQueryable<T>, WebAPI allows you to query the data set using some of the OData operators.  This can be really helpful for only returning the entities you really need on the client!

Creating the Client

Now that the project is set up, and the service is created, we can set up a web form page to load this data. 

Add jQuery to the page by adding the script tag in the head, or dragging and dropping it onto the page from the solution explorer.

Now create a simple list:

<ul id=”customerList>
 
</ul>
 

And then create the following jQuery function:

$(function () {
      $.ajax({
          url: '<%=Page.ResolveUrl("~/api/customers")%>',
          type: "GET",
          contentType: "application/json;charset=utf-8",
          statusCode: {
              200: function (results) {
 var customerList= '';
 for (var i = 0; i < results.length; i++) {
 var currentResult =results[i];
                      customerList += "<li>" + currentResult.FirstName + " " + currentResult.LastName + "</li>"
                  }
                  $('#customerList').html(customerList);
              }
          }
      });
  });

This function will call the new service method, and create a list item for each customer as shown here:

image

That is not very nice looking, so how about we use a grid instead?  Telerik’s Grid for ASP.NET AJAX already has support for binding to OData, and as I mentioned earlier, when you expose your entities using IQueryable<T> many of the same OData operators can be used.

To get this data to display in RadGrid, copy and paste the following:

<telerik:RadScriptManager ID="RadScriptManager1" runat="server">
 <scripts>
 <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" />
 <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" />
 <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js" />
 </scripts>
 </telerik:RadScriptManager>
 <telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" />
 <telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server">
 <telerik:RadGrid ID="RadGrid1" GridLines="None" runat="server" AutoGenerateColumns="true">
 <mastertableview commanditemdisplay="None" horizontalalign="NotSet" >
 <Columns>
 <telerik:GridBoundColumn DataField="FirstName" HeaderText="First Name" 
 UniqueName="FirstName" DataType="System.String" />
 <telerik:GridBoundColumn DataField="LastName" HeaderText="LastName" 
 UniqueName="LastName" DataType="System.String" />
 <telerik:GridBoundColumn DataField="Id" HeaderText="Id" Display="false" 
 UniqueName="Id" DataType="System.Int32" />
 </Columns>
 </mastertableview>
 <ClientSettings>
 <DataBinding Location="http://localhost:36955/api" ResponseType="JSON">
 <DataService TableName="Customers" Type="OData" />
 </DataBinding>
 <Scrolling AllowScroll="True" UseStaticHeaders="True" SaveScrollPosition="True" />
 </ClientSettings>
 </telerik:RadGrid>
 <telerik:RadWindowManager ID="RadWindowManager1" runat="server">
 </telerik:RadWindowManager>
 </telerik:RadAjaxPanel>

Now it should look something like this:

image

Much better!  Now we have data pulling from our new WebAPI controller, and displaying on an ASP.Net Web Form. 

That is where I will end today.  Next time we will take a look at editing this data, and saving it back to the controller, so stay tuned!

Happy Coding!

Download the RadControls trial today!

About the author

Iana Tsolova

Iana Tsolova

is Program Manager of Telerik’s ASP.NET AJAX division. She joined the company back in the beginning of 2008 as a Support Officer and has since occupied various positions at Telerik, including Senior Support Officer, Team Lead at one of the ASP.NET AJAX teams and Technical Support Director. Iana’s main interests are web development, reading articles related to geography, wild nature and latest renewable energy technologies.

11 Comments

Ben Hayat
Hi Josh;
I would like to pose my question by firstly paint the picture and then see how and why WebAPI can fit into this picture.
As you know, with .Net & ASP.Net 4.5, MSFT is introducing a morestreamed line data binding between the ASP.Net Ajax controls and EFentities. They sort of eliminated the presence of ObjectDataSource,where a control can bind directly to an EF entity. They also introduced anew data modeling scheme for better Data binding plus a better datavalidation on client using server's attributes. This new package shouldwork very nicely.
Now we are introducing WebAPI into this picture. Can you please describe how the WebAPI fits into the above scheme and package?
And also What would this WebAPI bring to table for the above system?
The second question would be:
a) Do I need to change my existing server side methods that currentlyuses EF in a synchronous mode that performs CRUD to new methods that aresuited for WebAPI?
b) Or Should WebAPI (and it's methods) be used by a different client (i.e. phones or tablet) via smaller bandwidth?
I think it's important to establish a relationship between WebAPI and existing WebForm apps.
Thank you in advance and looking forward to your point of view.
..Ben
Jack
Josh - does this mean we may see the Open Access Domain Model Service wizard upgraded to generate WepAPI code for us?  What about the WCF v3?
Thanks
jack
Cory
I'm guessing you were just being thorough, but that JS makes this seem overly complex. 
var url = '<%=Page.ResolveUrl("~/api/customers")%>';
$.get(url, function(results) {
     console.log(results);
});
var url = '<%=Page.ResolveUrl("~/api/customers")%>',
      params = { id:1 };
$.get(url, params, function(results) {
     console.log(results);
});
Jeff O'Connell
I tried following along by re-creating my own solution in VS2010 with ASP.Net MVC 4.0 beta. Everything works with the exception of the 
 return repository.Get(); 

in the ValuesController1.cs
I get a Compiler Error CS0103 exception
Where does repository come into play with this example?
Are you calling a Datasource called 'repository'?
Do you have any sample code of it?
Thanks Jeff
Joshua holt
@Ben: WebAPI provides an extremely easy way to expose object as resources as shown here. This can be really helpful when creating rich client experiences beyond just data-binding and validation. As an example, Todd and I have been working on a demo using Kendo, WebAPI, and OA.  In the demo we created a single page app, and installable mobile clients.  All interfaces consume the same WebAPI service!
A.  Of course! You can easily use EF to handle CRUD operations in a WebAPI controller.  WebAPI has model binding just like MVC (and ASP.NET 4.5 web forms). The biggest challenge you will face it how to expose complex data models at the service boundary; so that relationships do not trip up the serializer.  Complex relationships can cause the serializer to error out when trying to serialize circular references. (Order>OrderDetail>Order).
B. As I mentioned above, WebAPI works awesome anywhere you want to expose resources via HTTP.  Mobile applications are one great example :)  Feel free to shoot me an email if you would like to discuss more!
Joshua holt
@Jack:
I wrote a blog on this subject just last week, and the team should be publishing it this week on the OA Team blogs.  In essence, we do plan to provide support for WebAPI, but at this stage we want to capture as much customer feedback as possible; so that we can provide a useful implementation out of the box. 
@Cory:
You are correct of course!  I tend to not use the shortcut methods, but they are perfectly valid here.  
@Jeff:
Sorry, it appears I forgot to add the source to the post.  I will add it as soon as I get into the office!
Ben Hayat
<<As an example, Todd and I have been working on a demo using Kendo,WebAPI, and OA.  In the demo we created a single page app, andinstallable mobile clients.  All interfaces consume the same WebAPIservice!>>
Josh, I would love to see that demo on KendoUI site. Are you guys planning to publish it as a running app on KendoUI or Telerik site?
Thanks!
..Ben
Joshua Holt
Hi Ben,
I believe it will be published as a running app on the KendoUI site once we wrap it up.  :)
Joshua Holt
Hey Guys,
I wanted to let you know the source is available in my follow up post covering CRUD operations.  The download link is at the bottom of the blog. :)
Regards,
Josh
Joshua Holt
Hey Guys,
I wanted to let you know the source is available in my follow up post covering CRUD operations.  The download link is at the bottom of the blog. :)
Regards,
Josh
Jalpesh Vadgama
Nice work!!  May be we can see an alternative of web service and wcf

Comments

  1.    
      
      
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)
Read more articles by ASP.NET AJAX Team - or - read latest articles in Developer Tools
Product Families