Scott Hanselman

Tiny Happy Features #2 - ASP.NET Web API in Visual Studio 2012

August 11, 2012 Comment on this post [15] Posted in ASP.NET | ASP.NET Web API | Javascript | Open Source | Tiny Happy Features | VS2012
Sponsored By

REST, POX, and WCF compared to RESTtafarians, a guy with a bag on his head and Darth Vader

(UPDATE: See other Tiny Happy Features)

At some point soon lots of people are going to start writing these epic blog posts about Visual Studio 2012. They will include LOTS of screenshots (some good and some bad), some small code samples and minimal context. I can't speak for other teams; I can only talk about what we worked on. The <AngleBrackets/> folks in Azure Platform and Tools (ASP.NET, IIS, WCF, EF, Azure much and more) have been putting a lot of work into what I sometimes call "Death by a Thousand Tiny Cuts." It's the little irritants that are as frustrating (or more so) as the big missing features.

Rather than a giant super post (although I'll do that at some point) I thought I'd showcase some Tiny Happy Features that the team worked on just because it made life better. Some are large some are small, but all are tiny happy features.

There's Enterprise Web Services that use SOAP and WS-*.* and they are great for many transactional or complex scenarios. Then there are lighter weight RESTful web services or "Web APIs" that use JSON, XML and respect all of the goodness and stability that is the HTTP specification.

WCF is alive and well and ASP.NET is alive and well and there are reasons to use each technology. As this article says very well, "The world of SOAP and the world of HTTP services are very different. SOAP allows us to place all the knowledge required by our service in the message itself" vs. "you can use [Web APIs] to create HTTP services that only use the standard HTTP concepts (URIs and verbs), and to to create services that use more advanced HTTP features – request/response headers, hypermedia concepts etc."

Kelly Sommers wrote what I consider the best explanation of REST out there in "Clarifying REST." Whether you want to write RESTful resource-focused HTTP services or just POX or POJ (Plain Old XML or Plain Old JSON) services, you can do both with ASP.NET Web API. It's all part of the ASP.NET open source web stack.

Rick Strahl says that ASP.NET Web API is different than other frameworks because "it was built from the ground up around the HTTP protocol and its messaging semantics. Unlike WCF REST or ASP.NET AJAX with ASMX, it’s a brand new platform rather than bolted on technology that is supposed to work in the context of an existing framework. The strength of the new ASP.NET Web API is that it combines the best features of the platforms that came before it, to provide a comprehensive and very usable HTTP platform."

I encourage you to check out Rick's excellent analysis. Here's the features of ASP.NET Web API Rick likes:

  • Strong Support for URL Routing to produce clean URLs using familiar MVC style routing semantics
  • Content Negotiation based on Accept headers for request and response serialization
  • Support for a host of supported output formats including JSON, XML, ATOM
  • Strong default support for REST semantics but they are optional
  • Easily extensible Formatter support to add new input/output types
  • Deep support for more advanced HTTP features via HttpResponseMessage and HttpRequestMessage
    classes and strongly typed Enums to describe many HTTP operations
  • Convention based design that drives you into doing the right thing for HTTP Services
  • Very extensible, based on MVC like extensibility model of Formatters and Filters
  • Self-hostable in non-Web applications 
  • Testable using testing concepts similar to MVC

ASP.NET Web API

There's some lovely new samples at this Git Repository. Just "git clone https://git01.codeplex.com/aspnet" or download the zip. You can also familiarize yourself with ASP.NET and the Web API at the new http://www.asp.net/webapi site.

By the way, I'll be publishing a bunch (13!) of new videos showcasing Web API plus a lot of other Tiny Happy Features next week on the 15th. Each video will only be 5 minutes long and will be a great way to get up to speed on all the new tech over lunch.

To use the samples, follow the instructions on Henrik's blog post announcing them.

Here's one nice little sample that will perhaps cause you to rethink what you can accomplish with ASP.NET web technologies. It's a console application that hosts ASP.NET Web API. To be clear, there's no IIS involved.

In the setup instructions we have to register a port and user with HTTP.sys so the Operating System knows it's OK for send our little self-hosted app HTTP traffic. If you're familiar with WCF you may have done this before.

Here's the server. It's a Console App, minus error handling for clarity.

class Program
{
static readonly Uri _baseAddress = new Uri("http://localhost:50231/");

static void Main(string[] args)
{
// Set up server configuration
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(_baseAddress);

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

// Create server
var server = new HttpSelfHostServer(config);

// Start listening
server.OpenAsync().Wait();
Console.WriteLine("Listening on " + _baseAddress + " Hit ENTER to exit...");
Console.ReadLine();
server.CloseAsync().Wait();
}
}

That code sets up a route, starts the self-hosting process, and waits. Here's a controller at http://localhost:50231/Contact that will ECHO whatever contact you HTTP POST to it as content-type JSON. Note that Contact is a C# type as a parameter to Post().

public class ContactController : ApiController
{
public Contact Post(Contact contact)
{
return contact;
}
}

If I want, I can do a POST from another command line using curl and send some JSON into the server.

POSTing JSON from CURL to ASP.NET Web API

Here's the actual command line. The JSON is echo'ed back.

C:\>curl -X POST -H "Content-Type: application/json" -d "{ Name: 'Scott Guthrie', Age: 67}" http://localhost:50231/api/Contact

That's from the command line but I can also use System.Net.Http.HttpClient to make a call from .NET if I like:

HttpClient client = new HttpClient();

Contact contact = new Contact {
Name = "Henrik",
Age = 100
};

// Post contact
Uri address = new Uri(_baseAddress, "/api/contact");
HttpResponseMessage response = await client.PostAsJsonAsync(address.ToString(), contact);

// Check that response was successful or throw exception
response.EnsureSuccessStatusCode();

// Read result as Contact
Contact result = await response.Content.ReadAsAsync<Contact>();

Console.WriteLine("Result: Name: {0} Age: {1}", result.Name, result.Age);

See how the C# Contact object moves back and forth between the JSON world and C# world easily? That's the JSON.NET open source library making that happen.

JSON and JavaScript is really dynamic, though, and often it's a hassle to try to "deserialize" really dynamic JSON objects into strongly-typed .NET structures. JSON.NET and ASP.NET Web API's model binding offer a happy medium - a middle ground - called JToken.

public class ContactController : ApiController
{
public JToken Post(JToken contact)
{
return contact;
}
}

Check out the watch window as the JSON comes in:

Using JToken to catch a JSON payload

Using JToken gives me a dynamic container but also a DOM-like navigation model. But if that's not dynamic enough for me, why can't my method's parameter just take a "dynamic."

C# is statically typed, sure, but that doesn't mean I can't statically type something dynamic. ;)

Again, note the watch window.

Using dynamic to catch JSON post payloads

See how JSON is moving around the system without any impedance mismatch. The power of C# isn't slowing down the flexibility of JavaScript and JSON.

It makes me happy when things work as they should.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
August 11, 2012 10:08
Its great Microsoft made this framework just as pluggable as ASP.NET MVC. For example, it is even possible to add versioning to ASP.NET web API without much effort: http://damsteen.nl/blog/implementing-versioning-in-asp.net-web-api
Dev
August 11, 2012 13:48
Dude, completely OT, but I have to say it. I ROFL when I saw Nandor Tanczos as your 'REST' guy; funny how he turns up in a generic Rasti Guy search (http://www.parliament.nz/en-NZ/MPP/MPs/Former/4/6/a/48PlibMPsFormerNandorTanczos1-Tanczos-Nandor.htm)
August 11, 2012 17:55
LOL - Scott Guthrie is 67? - Amazing... What is his secret?
August 11, 2012 20:22
I think you may be interested in the "ram-jet" powered JSON facility Mehdi Gholam has been creating at CodeProject:

http://www.codeproject.com/Articles/159450/fastJSON

http://www.codeproject.com/Articles/345070/fastBinaryJSON

And Mehdi's "RaptorDB:"

http://www.codeproject.com/Articles/375413/RaptorDB-the-Document-Store

"NoSql, JSON based, Document store database with compiled .net map functions and automatic hybrid bitmap indexing and LINQ query filters (now with standalone Server mode, Backup and Active Restore, Transactions, Server side queries)"

His extensive comparative performance tests against other (including MS provided stack) implementations are rather amazing.

best, Bill
August 12, 2012 17:31
Speaking of screenshots, can anyone who has access to VS11 RTM say if they've fixed their horrible icon scaling at higher DPI settings? This is what I see in RC: http://i.imgur.com/zwKPE.png
August 13, 2012 13:14
Great post Scott. Self hosting of WebApi is one of the best features as it gives a lot of flexibility when it comes to things like unit testing.

Just a note: you can actually combine the server startup and the URL invocation into one project rather than two by providing a short action:
server
.OpenAsync()
.ContinueWith(t => {
var c = new HttpClient();
// ... etc.
})
.Wait();

This is really helpful for setting up unit tests (as everything becomes self-contained)
August 13, 2012 18:42
Hi, just to say I have created a little utility :
http://httpsysmanager.codeplex.com/ to facilitate http.sys configuration part :)
Here are some internal details on http://www.codeproject.com/Articles/437733/Demystify-http-sys-with-HttpSysManager

Nothing fancy, it is just a Tiny Happy App :)
August 13, 2012 20:21
Thanks. This was what I needed (self hosting).

Does self hosting use HTTP.SYS as well? If so, is there a way to request uri security grants from within .Net code?
August 14, 2012 6:28
As a lone dev, I can't afford to spend all that time mastering WCF intricacies: customers don't really like to be invoiced for time spent on infrastructure details, they'd rather pay for their business problems getting solved, so I'm glad that people like Glenn Block looked into simplifying the common use cases of WCF and produce something with a sane default behaviour that will be extremely useful for building APIs.
I also love the fact that it can easily be self-hosted, not every problem needs the headache of administering a full-blown web server.

So kudos to the team, and thank you Scott for these previews.
August 20, 2012 15:41
Nice post Scott

We just completed the first version of our API using Web API - I took the time to document the process we went through here in a series of 9 posts:

http://bit.ly/etwebapi

Returning JToken's or dynamic works really well, also you using nested IDictionary<string,object> instances or performing JToken rewriting in your MediaTypeFormatter works well too for piggy-backing dynamic content into your static view models - and allows you stick with static typing for the most part within your API controller implementation.

Keep up the great work :)

Cheers,

Alex
January 10, 2013 21:29
Scott,

Do you know of anyway that a dynamic parameter will work for a request that contains XML?

For example:

POST http://localhost:52753/api/Test HTTP/1.1
User-Agent: Fiddler
Host: localhost:52753
Accept: application/xml
Content-Type: application/xml; charset=utf-8

<Root>
<Message>Hello</Message>
</Root>

and have this bind into:

public dynamic Post([FromBody]dynamic xml)
{
return xml;
}
January 10, 2013 22:11
Andy - No, but this isn't a WebAPI issue. I don't think there are any XML parsers on .NET that use Dynamic. If there were, you could write a model binder quickly.
March 25, 2013 10:19
What is the best way for putting in a request for XML parsers to support "dynamic" on the radar? Connect? From a WEBAPI perspective the promise of content negotiation falls short for PATCH requests wherein you are looking to accept a set of key value pairs typed as "dynamic" instead of a full blown DTO.
June 10, 2013 19:39
Scott,

It is nice to see Asp.NET Web Api as new feature. But I don't understand why the Web Api is part of Asp.NTE MVC project. Off course it is known that it uses MVC controller. But this doesn't mean it should be part of MVC. Here is a simple scenario. I want to provide simple REST service using Web APi. Mind you no MVC UI required and no Model it required. The POCO come as independent project(Library or services). And the only piece I'll use going to be Controller. Model and View will be deleted. I don't want to keep them there, because they are not relevant to my project. Mind you I'm going to provide RESTful service.

So to provide RESTful service why on earth I do need to create MVC project. Don't understand the relevance and why it is added as part of MVC project

Regards
July 08, 2013 12:09
Master man,
You can use the MVC ui functionality on your Web API to send rendered content instead of just serialized objects, so I think it is appropriate to retain that functionality built in.

As an aside I wish SignalR would have a similarly tighter binding with MVC so as to make it easier to have it push dynamic rendered content in the MVC model.
B

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.