Suggested Videos
Part 36 - Web API versioning using querystring parameter
Part 37 - Web API versioning using a custom header
Part 38 - Web API versioning using accept header
In this video we will discuss versioning a Web API Service using vendor specific media types. This is continuation to Part 38. Please watch Part 38 from Web API tutorial before proceeding.
So here is what we want to be able to do. Instead of using the standard media types like application/xml or application/json, we want to use our custom media type as shown below in fillder
Notice in the media type, we have the version of the service we want. Custom media types have vnd prefix. vnd indicates that it is a vendor specific media type. So from our CustomControllerSelector class we want to read the version number from the custom media type we have specified.
The changes that are required are commented, so it is self-explanatory.
So at this point, if we issue a request using our custom media type from fiddler, we get version 1 of student objects in JSON format. If you specify version 2 (v2) instead of version 1 (v1), we get version 2 student objects as expected.
Response from the web api service
However, if we specify that we want xml format instead of json in the request as shown below. We still get JSON formatted result instead of XML formatted result.
Response from the web api service
This is because we have not added our custome media types to the respective media type formatters (JsonFormatter and XmlFormatter).
To add the custom media types to the JsonFormatter, include the following 2 lines of code in WebApiConfig.cs file
To add the custom media types to the XmlFormatter, include the following 2 lines of code in WebApiConfig.cs file
So at this point, let's issue another request using our custom media type from fiddler
Notice we get version 1 of student objects in XML format as expected
Part 36 - Web API versioning using querystring parameter
Part 37 - Web API versioning using a custom header
Part 38 - Web API versioning using accept header
In this video we will discuss versioning a Web API Service using vendor specific media types. This is continuation to Part 38. Please watch Part 38 from Web API tutorial before proceeding.
So here is what we want to be able to do. Instead of using the standard media types like application/xml or application/json, we want to use our custom media type as shown below in fillder
Notice in the media type, we have the version of the service we want. Custom media types have vnd prefix. vnd indicates that it is a vendor specific media type. So from our CustomControllerSelector class we want to read the version number from the custom media type we have specified.
The changes that are required are commented, so it is self-explanatory.
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
namespace WebAPI.Custom
{
public class CustomControllerSelector : DefaultHttpControllerSelector
{
private HttpConfiguration _config;
public CustomControllerSelector(HttpConfiguration config) : base(config)
{
_config = config;
}
public override HttpControllerDescriptor
SelectController(HttpRequestMessage request)
{
var
controllers = GetControllerMapping();
var
routeData = request.GetRouteData();
var
controllerName = routeData.Values["controller"].ToString();
string versionNumber = "1";
// Comment the code that gets the version number from
Query String
// var versionQueryString =
//
HttpUtility.ParseQueryString(request.RequestUri.Query);
//if (versionQueryString["v"] != null)
//{
// versionNumber
= versionQueryString["v"];
//}
// Get the version number from Custom version header
//string customHeader =
"X-StudentService-Version";
//if (request.Headers.Contains(customHeader))
//{
// // If
X-StudentService-Version:1 is specified twice in the request
// // then in
versionNumber variable will get a value of "1,1"
// versionNumber
= request.Headers.GetValues(customHeader).FirstOrDefault();
// // Check if
versionNumber string contains a comma, and take only
// // the first
number from the comma separated list of version numbers
// if
(versionNumber.Contains(","))
// {
//
versionNumber = versionNumber.Substring(0, versionNumber.IndexOf(","));
// }
//}
// Get the version number from the Accept header
// Users can include multiple Accept headers in the
request
// Check if any of the Accept headers has a parameter with
name version
//var acceptHeader = request.Headers.Accept.Where(a =>
a.Parameters
//
.Count(p => p.Name.ToLower() == "version") > 0);
//// If there is atleast one header with a
"version" parameter
//if (acceptHeader.Any())
//{
// // Get the
version parameter value from the Accept header
// versionNumber
= acceptHeader.First().Parameters
//
.First(p => p.Name.ToLower() == "version").Value;
//}
// Get the version number from the Custom media type
// Use regular expression for mataching the pattern of the
media
// type. We have given a name for the matched group that
contains
// the version number. This enables us to retrieve the
version number
// using the group name("version") instead of
ZERO based index
string regex =
@"application\/vnd\.pragimtech\.([a-z]+)\.v(?<version>[0-9]+)\+([a-z]+)";
// Users can include multiple Accept headers in the
request.
// Check if any of the Accept headers has our custom media
type by
// checking if there is a match with regular expression
specified
var
acceptHeader = request.Headers.Accept
.Where(a => Regex.IsMatch(a.MediaType, regex, RegexOptions.IgnoreCase));
// If there is atleast one Accept header with our custom
media type
if
(acceptHeader.Any())
{
// Retrieve the first custom media type
var match = Regex.Match(acceptHeader.First().MediaType,
regex, RegexOptions.IgnoreCase);
// From the version group, get the
version number
versionNumber = match.Groups["version"].Value;
}
HttpControllerDescriptor controllerDescriptor;
if
(versionNumber == "1")
{
controllerName = string.Concat(controllerName, "V1");
}
else
{
controllerName = string.Concat(controllerName, "V2");
}
if
(controllers.TryGetValue(controllerName, out
controllerDescriptor))
{
return controllerDescriptor;
}
return null;
}
}
}
So at this point, if we issue a request using our custom media type from fiddler, we get version 1 of student objects in JSON format. If you specify version 2 (v2) instead of version 1 (v1), we get version 2 student objects as expected.
Response from the web api service
However, if we specify that we want xml format instead of json in the request as shown below. We still get JSON formatted result instead of XML formatted result.
Response from the web api service
This is because we have not added our custome media types to the respective media type formatters (JsonFormatter and XmlFormatter).
To add the custom media types to the JsonFormatter, include the following 2 lines of code in WebApiConfig.cs file
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("application/vnd.pragimtech.students.v1+json"));
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("application/vnd.pragimtech.students.v2+json"));
To add the custom media types to the XmlFormatter, include the following 2 lines of code in WebApiConfig.cs file
config.Formatters.XmlFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("application/vnd.pragimtech.students.v1+xml"));
config.Formatters.XmlFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("application/vnd.pragimtech.students.v2+xml"));
So at this point, let's issue another request using our custom media type from fiddler
Notice we get version 1 of student objects in XML format as expected
What is the difference between Aps web services,web API, and wcf? when use one over the other? Please explain in a video.
ReplyDelete