In ASP.NET Web API, a controller is a class that handles HTTP requests. The public
methods of the controller are called action methods or simply actions. When the
Web API framework receives a request, it routes the request to an action.
To determine which action to invoke, the framework uses a routing table. If you are
hosting Web API from ASP.NET, the routing table is created in the Global.asax
file. By default when you use Visual Studio to create a new Web API project,
the project template creates a default route for you.
If this all sounds a lot like ASP.NET MVC, it's because it is. Once a matching
route is found, Web API selects the controller and the action.
To find the controller, Web API adds "Controller" to the value of the {controller}
variable. To find the action, Web API looks at the HTTP method, and then looks
for an action whose name begins with that HTTP method name. Other placeholder
variables in the route template, such as {id}, are mapped to action parameters,
just as with ASP.NET MVC.
ASP.NET Web API has a pipeline for processing HTTP messages on both the client and
server. The client and server sides are designed to be symmetrical but independent;
you can use each half by itself. Both sides are built on some common objects:
HttpRequestMessage represents the HTTP request.
HttpResponseMessage represents the HTTP response.
HttpMessageHandler objects process the request and response.
This provides for a nice, compact, and efficient way of transmitting Request and
Response objects that contain all the data for the payload involved.
You can also write custom message handlers, which would derive from the System.Net.Http.DelegatingHandler
class.
In ASP.NET Web API, a media formatter is an object that can:
Read CLR objects from an HTTP message body
Write CLR objects into an HTTP message body
Web API provides media-type formatters for both JSON and XML. The framework inserts
these formatters into the pipeline by default. Clients can request either JSON
or XML in the Accept header of the HTTP request.
The Web API can either be self-hosted, or run from within an ASP.NET web application.
Although ASP.NET Web API is packaged with ASP.NET MVC, it is easy to add Web
API to a traditional ASP.NET Web Forms application.
ASP.NET Web API is also designed so that you can use your choice of tracing/logging
library, and you can inject dependencies into your ASP.NET Web API controller
using the Web API dependency resolver.
To put this demo together, I started out with the "Contacts" Demo provided
by Microsoft, and added a real backing store via SQL Server and the ServiceStack
ORMLite infrastructure. The infrastructure begins life in the Application_Start
event of the Global class:
public static OrmLiteConnectionFactory DbFactory;
protected void Application_Start()
{
DbFactory = new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString, SqlServerOrmLiteDialectProvider.Instance);
OrmLiteConfig.DialectProvider = new SqlServerOrmLiteDialectProvider();
using (IDbConnection dbConn = DbFactory.OpenDbConnection())
{
using (IDbCommand dbCmd = dbConn.CreateCommand())
{
const bool overwrite = false;
dbCmd.CreateTables(overwrite, typeof (Contact));
}
}
RegisterApis(GlobalConfiguration.Configuration);
}
The above code creates a static instance of the OrmLiteConnectionFactory, and then
creates the Contacts SQL Server table directly from the Contact class. This only
happens once, the overwrite bool parameter will not overwrite if the table already
exists. It then goes on to handle registering the APIs.
My Contact class looks like the following:
using System;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using ServiceStack.DataAnnotations;
using ServiceStack.DesignPatterns.Model;
namespace ContactManager.Models
{
[Alias("Contacts")]
public class Contact :IHasId<Int32>
{
[PrimaryKey]
[AutoIncrement]
public int Id { get; set; }
[StringLength(350)]
public string Name { get; set; }
[StringLength(350)]
public string Address { get; set; }
[StringLength(35)]
public string City { get; set; }
[StringLength(25)]
public string State { get; set; }
[StringLength(12)]
public string Zip { get; set; }
[StringLength(350)]
public string Email { get; set; }
[StringLength(350)]
public string Twitter { get; set; }
[StringLength(350)]
public string Self
{
get { return string.Format(CultureInfo.CurrentCulture, "contact/{0}", this.Id); }
set { }
}
}
}
Note that I am using DataAnnotations attributes to set up the table schema. And
here is the ContactRepository that does all the "heavy lifting":
using ServiceStack.OrmLite;
namespace ContactManager.Models
{
using System.Collections.Generic;
using System.Linq;
public class ContactRepository : IContactRepository
{
public ContactRepository()
{
}
public void Update(Contact updatedContact)
{
WebApiApplication.DbFactory.Exec(dbCmd => dbCmd.Update(updatedContact));
}
public Contact Get(int id)
{
return WebApiApplication.DbFactory.Exec(dbCmd => dbCmd.GetById<Contact>(id));
}
public List<Contact> GetAll()
{
using (IDbConnection dbConn = WebApiApplication.DbFactory.OpenDbConnection())
{
using (IDbCommand dbCmd = dbConn.CreateCommand())
{
using (IDbTransaction dbTrans = dbCmd.BeginTransaction())
{
return dbCmd.Select<Contact>();
}
}
}
}
public void Post(Contact contact)
{
WebApiApplication.DbFactory.Exec(dbCmd => dbCmd.Save(contact));
}
public void Delete(int id)
{
WebApiApplication.DbFactory.Exec(dbCmd => dbCmd.DeleteById<Contact>(id));
}
}
}
This is pretty much all it takes to wire in ServiceStack ORMLite to any application,
either MVC or Web API. When you download the Demo, you'll need to create
a new SQL Server Database "TEST" first. The application itself takes
care of creating the table from the model. All of the ServiceStack assemblies
needed are located in the /Libs folder. ServiceStack ORMLite is lightning fast
(just behind Dapper-Dot-Net, the performance speed champion) and it's friendly
extension methods make it extra easy to perform the kinds of CRUD operations
you need.
You can download the Visual Studio 2010 solution and accompanying assemblies here.