Archive
Custom filters in AngularJS
In this post I am going to show you how easy it is to write custom filters in AngularJS and for the simplicity of the demo I am going to display a list of cron-jobs in a tabular data. Each job has details like the Id, action etc. and has a status which is represented in numbers like 0,1,2 etc. This may be suitable from a storage or system point of view but is not that user-friendly, so lets write a custom filter to transform numeric values into user-friendly status.
First we start with an AngularJS controller "CronJobsController" and it will be responsible for calling the cronjobs ASP.NET Web API.If the call is successful the returned data is assigned to $scope.jobs object so that we can bind the data to our view.
app.js
var app = angular.module('mainApp', []); app.controller('CronJobsController', function ($scope,$http) { $scope.jobs = []; $http({ method: 'GET', url: '/api/cronjobs' }) .then(function(response) { $scope.jobs = response.data; },function(reason) { $scope.error = reason.data; }); });
Next step is to wire up the "myApp" to the HTML page by using the ng-app directive.
CronJobs.html
<body ng-app="mainApp"> <!--Html omitted for brevity --> </body>
Now I am going to create the view by adding some table mark-up and use bootstrap to format the HTML table. For data binding I’m going to use the ng-repeat directive to enumerate through the jobs and bind the data to the table.
CronJobs.html(cont.)
<div class="row"> <!-- Jobs Controller Scope --> <div class="col-md-12" ng-controller="CronJobsController"> <table class="table table-striped"> <thead> <tr> <th>Id</th> <th>Correlation Id</th> <th>Action</th> <th>Created</th> <th>Status</th> </tr> </thead> <tbody> <tr ng-repeat="job in jobs"> <td>{{job.id}}</td> <td>{{job.correlationId}}</td> <td>{{job.action}}</td> <td>{{job.created | date:'dd-MM-yyyy'}}</td> <td>{{job.status}}</td> </tr> </tbody> </table> </div> <!-- End of Jobs Controller Scope --> </div>
Lets run the application and we can see that everything is working perfectly.
Now we are going to build our custom filter "status" which will return a user-friendly status based on the numeric value.
statusfilter.js
/// <reference path="app.js" /> app.filter('status', function() { return function(status) { switch(status) { case 0: return "Not Started"; case 1: return "In Progress"; case 2: return "Completed"; default: return "Unknown"; } } })
Nothing special here a simple switch case statement returning user-friendly text and all is left is to apply this filter to our model’s status property as shown in below code snippet.
<td>{{job.status | status}}</td>
And after applying the filter we can see the user-friendly status is displayed instead of the numbers.
It’s a very simple yet powerful feature and another reason to love AngularJS.
ASP.NET Core – Exceeds 1.15 Million request/s
Congratulations to the ASP.NET Core team for hitting this amazing milestone of 1.15 Million request/s http://www.ageofascent.com/asp-net-core-exeeds-1-15-million-requests-12-6-gbps/ . Now is an amazing time to work with ASP.NET Web API and AngularJS.
Testing Web API
Continuing with my previous post on Implementing Web API Versioning using OWIN, in this post I am going to show how to write unit test for your Web APIs.
As we know that the beauty of OWIN is able to run your web application independent of the web server and based on this principle the Microsoft.Owin.Testing takes advantage of this feature to host the Web API in memory and execute the methods. Very simple and straight forward.
Lets get started by creating a new Unit Test project in Visual Studio and get the Microsft.Owin.Testing package from the Nuget Server as shown below.
Next step is to create a custom Startup class and bring in any services or OWIN Middleware which our Web API depends upon. As this is a demo Web API application I will just configure the DefaultVersionSelector we build in the previous post.
CustomStartup.cs
public class CustomStartup { public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); config.Routes.MapHttpRoute( "DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional, version = "1" }); config.Services.Replace( typeof(IHttpControllerSelector), new DefaultVersionControllerSelector( config, new DefaultVersionSelector())); app.UseWebApi(config); } }
As you can see nothing special in the startup class it is identical to our Web API project startup class and all I am doing is registering my DefaultVersionSelector and it dependencies and asking the IAppBuilder to invoke the OWIN Web API Middleware.
Now we are going to write a unit test which will use the OWIN testing component and invoke a simple get on our values controller.
WhenUsingOwinTestServer.cs
public class WhenUsingOwinTestServer { private const string ContentTypeJsonVersion1 = "application/json;version=1"; private const string AcceptHeader = "Accept"; private const string RequestUri = "/api/values"; private const string ExpectValueVersion1 = "[\"value1-Version1\",\"value2-version1\"]"; [TestMethod] public void ShouldBeAbleToGetResultForVersion1() { using (var server = TestServer.Create<CustomStartup>()) { var client = server.HttpClient; client.DefaultRequestHeaders.Add(AcceptHeader, ContentTypeJsonVersion1); var task = server.HttpClient.GetAsync(RequestUri); var response = task.Result.Content.ReadAsStringAsync(); Assert.AreEqual(ExpectValueVersion1, response.Result); } } }
As you can see in the above code we are using the TestServer to host Web API with our custom startup class. First we get a reference of the it’s HttpClient object and add our accept header with the versioning information. Next we make a GET request at the api/values end point,as everything is happening in memory you can see we don’t specify the web server in our URI.
Rest is pretty straight forward and we assert that the expected values and the results do match.
Implementing Web API Versioning using OWIN
In my previous post "Designing Web API Versioning" I covered some of the design aspects of versioning and in this post I am going to show you how to implement versioning in Web APIs using OWIN.
First I am going to define a simple interface so that we can plug this in the OWIN Pipeline and it allows a nice separation of Concerns and promotes Single Responsibility principle.
IVersionSelector.cs
public interface IVersionSelector { string GetVersion(HttpRequestMessage request, IHttpRoute route); }
As you can see the interface is a pretty straight forward, it has dependency on the HttpRequestMessage as well as IHttpRoute and returns the version number. Also lets take care of some of the "Magic String" problem by creating a constant class as show below.
OwinConstants.cs
public static class OwinConstants { public const string GET = "GET"; public const string POST = "POST"; public const string PUT = "PUT"; public const char EqualsDelimiter = '='; public const char Period = '.'; public const char Underscore = '_'; public const char Semicolon = ';'; public const string Version = "version"; public const string VersionPrefix = "V"; public const string RequestMethod = "owin.RequestMethod"; public const string Controller = "controller"; public const string ContentType = "Content-Type"; }
In that post I also mentioned that the version should be passed as an Accept header if it’s a GET and Content-Type header if it is a POST or PUT. However, when it comes to DELETE you don’t need a version as you are DELETING a resource and from a resource point of view it doesn’t make any sense to specify a version to be deleted. For example at a resource like /api/customer/1 it is very clear that you are looking for customer resource with an id 1 and for delete you just want to delete that id irrespective of what version you are supporting for that Web API.
So our logic will do a simple check from the OWIN pipeline to identity what the request type is and based on the type we extract the relevant header either from the Accept header or from the Content-Type header.
Another important thing to consider is that what do we do if there are no headers supplied? Depending on your requirements and discussion you may implement it differently. However, in my implementation I will use the one which is defined in the route table as a fall back value.
Lets put this all together in the code to see how it looks.
DefaultVersionSelector.cs
public class DefaultVersionSelector : IVersionSelector { private const string versionFormat = "version={0}"; public string GetVersion(HttpRequestMessage request, IHttpRoute route) { object routeVersion = string.Empty; string headerVersion = string.Empty; var owinEnvironment = request.GetOwinEnvironment(); if (request.Method.Method == OwinConstants.POST || request.Method.Method == OwinConstants.PUT) { headerVersion = GetVersionFromContentType(request); if (!string.IsNullOrEmpty(headerVersion)) { return headerVersion; } } if (request.Method.Method == OwinConstants.GET) { headerVersion = GetVersionFromAcceptHeaderVersion(request); if (!string.IsNullOrEmpty(headerVersion)) { return headerVersion; } } route.Defaults.TryGetValue(OwinConstants.Version, out routeVersion); return routeVersion as string; } private string GetVersionFromContentType(HttpRequestMessage request) { var versionList = new List<string>(); var version = string.Empty; if (request.Content.Headers.ContentType == null) { throw new HttpResponseException(request.CreateResponse(HttpStatusCode.NotAcceptable)); } request.Content.Headers.ToList().ForEach(x => { if (x.Key.Contains(OwinConstants.ContentType)) { foreach (var item in x.Value.ToList()) { if (item.Contains(OwinConstants.Version)) { version = item.Split(OwinConstants.EqualsDelimiter)[1]; } } } }); return version; } private string GetVersionFromAcceptHeaderVersion(HttpRequestMessage request) { string version = string.Empty; request.Headers.Accept.ToList().ForEach(headerValue => { headerValue.Parameters.ToList().ForEach(v => { version = v.Value; }); }); return version; } }
Pretty straight forward and now we will hook the above version selector into the ASP.NET Web API pipeline by simply inheriting from the DefaultHttpControllerSelector and overriding the quot&;SelectController" method, it’s that simple.
DefaultVersionControllerSelector.cs
public class DefaultVersionControllerSelector : DefaultHttpControllerSelector { private const string versionFormat = "version={0}"; private HttpConfiguration config; private IVersionSelector versionSelector; public DefaultVersionControllerSelector(HttpConfiguration config, IVersionSelector versionSourceFactory) : base(config) { this.config = config; this.versionSelector = versionSourceFactory; } public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { var controllers = GetControllerMapping(); var routeData = request.GetRouteData(); var controllerName = routeData.Values[OwinConstants.Controller].ToString(); var owinEnvironment = request.GetOwinEnvironment(); var version = versionSelector.GetVersion(request, routeData.Route); version = version.Replace(OwinConstants.Period, OwinConstants.Underscore); HttpControllerDescriptor controllerDescriptor; owinEnvironment.Add(OwinConstants.Version, new string[] { string.Format(versionFormat,version) }); request.SetOwinEnvironment(owinEnvironment); var versionedControllerName = string.Concat(controllerName, OwinConstants.VersionPrefix, version); HttpControllerDescriptor versionedControllerDescriptor; if (controllers.TryGetValue(versionedControllerName, out versionedControllerDescriptor)) { return versionedControllerDescriptor; } if (!string.IsNullOrEmpty(version) && versionedControllerDescriptor == null) { throw new HttpResponseException( request.CreateResponse(HttpStatusCode.NotAcceptable)); } var defaultControllerName = routeData.Route.Defaults[OwinConstants.Controller].ToString(); controllers.TryGetValue(defaultControllerName, out controllerDescriptor); return controllerDescriptor; } }
As you can see from the above code, first we extract controller name from the route data and then extract the OWIN environment variable from the HTTPRequestMessage object. We also took care of minor version of API by checking for a period delimiter in the version.
If we happen to find one then we replace the period delimiter with an underscore, as this will allow us to map the version to a valid C# controller class. For example if the version is specified as "version=1.1" for a controller name "values" then the output controller name will be "Values1_1Controller".
After this we try to get the list of all the controllers using the base class and check if we can create a controller using the route value, controller name and the version. If we succeed we return the controller descriptor as is otherwise we fall back to the default supported version of the controller which we are going to specify in routing configuration. I know the above explanation can be bit confusing and hard to understand but don’t worry it will all come together once I show you the routing configuration.
Lets create two controller and I’ll just use the run-of-the-mill "ValuesController" for simple illustration and the name of the two versioned controllers are going to be Values1Controller for version 1 and Values1_1Controller for version 1.1 as shown below.
ValuesV1Controller.cs
public class ValuesV1Controller : ApiController { public IEnumerable<string> Get() { return new string[] { "value1-Version1", "value2-version1" }; } }
ValuesV1_1Controller.cs
public class ValuesV1_1Controller : ApiController { public IEnumerable<string> Get() { return new string[] { "value1-Version1.1", "value2-version1.1" }; } }
And this is where the routing magic happens in our OWIN startup class.
Startup.cs
public class Startup { public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); config.Routes.MapHttpRoute( "DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional, version= "1" }); config.Services.Replace(typeof(IHttpControllerSelector), new DefaultVersionControllerSelector(config, new DefaultVersionSelector())); app.UseWebApi(config); } }
Now I am going to use POSTMAN to request two GETS one for version 1 and for version 1.1 as shown below.
VERSION 1
VERSION 1.1
And as you can see from the returned data that the version selector is working correctly and we are hitting the right controller.
Designing Web API Versioning
In this post I am going to talk about some of the commonly used Web API versioning strategy and hope it will help you decide which one is best suitable for your scenario.You will also see that there is no right or wrong way of designing them but I am always about options and different approaches, ultimately it is you who have to decide which approach is best suitable for you.
Uri based approach:
In this type of versioning strategy the versioning is embedded in the URI and probably the most popular one.However I personally think it is quite anti-REST as with each version the URI changes. REST is very resource oriented and it means once you have defined the URI(address) to the resource then it shouldn’t change just because you have a new version of that resource. This also means that the physical URI surface area will increase in terms or URIs and the number of deployments.
Lets take a look at an example
Host: api.constosco.com
Accept:application/json
As you can see when a new version v2 is released the URI for the user resource will change and lot of your clients will have to point the URI to http://api.contosco.com/v2/user. The clients will have to keep up with your latest version if they prefer to use your latest version all the time. There is no easy way to make the version optional and return the latest version but in terms of ease and implementation it is the best approach.
Query string based approach:
In this type of strategy the versioning is appended as a query string and it is quite popular too. The version is passed as a query string so the URI doesn’t change when the version is changed, however make sure you are very clear on how you will handle versioning when the versioning is not provided.
Host: api.constosco.com
Accept:application/json
But consider this that the query string parameter is optional, so what would happen if somebody request it as http://api.contosco.com/product/1234. Do you return the oldest supported version or do you always return the latest version. There is no easy answer to this and depending on your requirement and how you foresee your Web API’s changing you might choose one over the other.
In my personal experience always return the latest version as this will allow your API consumers to either stick to the older version by specifying the version number or deal with the latest version if there are any breaking changes.
Content Negotiation based approach:
This is my favorite one and is getting slowly popular and in my opinion more REST than the above two.In this strategy the version is passed as content negotiation header. This way the version doesn’t appear nor in the URI or in the query string and the client doesn’t have to really change much to keep up with your latest version. However you still have to decide how do you handle the default versioning when no version is specified as part of content negotiation.
Host: api.constosco.com
Content-Type:application/vnd.constosco.1.0
Where the "1.0" at the end specifies the version and the application/vnd specifies it is a vendor specific header. Another thing I have noticed is that some people because of ease pass the version in the "Accept" header even if it is an HTTP POST or PUT. I think if you are going down this path then make sure "Accept" is for GET and "Content-Type" is for POST or PUT.
Host: api.constosco.com
Accept:application/json;version=1
And this is how the POST will look like.
Host: api.constosco.com
Content-Type:application/json;version=1
Custom Request Header based approach: Last but not the least is using a custom “x-*” header to specify the version and specifying a date as the version. This is something I noticed when I first started looking into your Azure Service Bus and how the QueueClient and TopicClient build the version header into their request. I guess this is a trend Microsoft have started and you can see it across the Azure Platform. I really like this approach and may be in my next project I’ll get a chance to implement it.
Host: api.constosco.com
x-ms-version:2015-05-25
Another aspect of the Web API versioning design is that, how many versions should you keep on supporting and like many software philosophies there is no definitive answer. In my experience maintaining and supporting multiple versions of Web API can be very complex,error prone, at times cruel and can prove very costly (both financially and mentally). So make sure you are designing it correctly and your upper management understand the complexity behind deployment, bug fixes, writing and fixing test etc while you are supporting so many versions. The general rule of thumb in my personal experience is to only support 2 versions of any given resource. Also make sure you have clear strategy of maintaining versions for related resources.
Deprecating older versions:
The simplest way to inform the clients that the version they requested for a resource is deprecated is by adding a “Deprecated” header with a value “true” to the response. Let say that the request from the client for a product with id 1234 is something like this.
Host: api.constosco.com
Accept:application/json;version=1
Then the return response should be
Content-Type: application/json; version=1
Deprecated: true
{"id":"1234", "name":"Brown Rice", "trade-number":"99804169"}
I hope this post has given some insight into the Web API versioning and in the next post I’ll show some code to show how this all comes together.Happy versioning !!! 🙂
Web API and Swagger
Nice post on Web API Documentation using Swagger http://bitoftech.net/2014/08/25/asp-net-web-api-documentation-using-swagger/ and download the sample here
OWIN and Web Api
In this post I am going to talk about how to get started with WEB API project with OWIN . As usual I am going to start with File > New Project > ASP.NET Web Application > Empty Solution and run the following Powershell command to get all the necessary OWIN packages from nuget.
PM> Install-Package Microsoft.Owin.Host.SystemWeb
PM> Install-Package Microsoft.Owin.Diagnostics
As you may have noticed the second package is to run OWIN Middleware on IIS but you could easily change that to "OWIN Self host" and spawn the web api on a console application with no dependencies on IIS.
The primary motivation and goals of OWIN specification is to develop web application which are independent of Web Server technology like IIS. Another goal is to move away from the System.Web.dll as it’s a 13-year-old assembly. That time it served it’s purpose as it was designed mainly keeping ASP.NET Web Forms in mind but now has a lot of dead weight when it executes code. We still can’t get away with it but in the ASP.Net vNext it is gone and your web application will run faster and will scale better.
For more information on OWIN please visit the http://owin.org/ website.
Anyways back to OWIN, now we are going to write a start-up class which the OWIN runtime will use it to bootstrap our web application and this is how the start-up code looks like.
Startup.cs
public class Startup { public void Configuration(IAppBuilder app) { app.UseWelcomePage(); } }
This is how the OWIN pipeline identifies the startup routine with the above method signature. As you can see it takes an interface IAppBuilder in which you can plug your own middleware and in the above code we are plugging the welcome page middleware component to display the page. This is the pattern which is used in development where you will develop your own middleware and plug that into the app builder.
Now when we run the application we can see the OWIN "Welcome page "running using IIS Express.
In the next step I am going to add a simple Customer Controller as shown below.
CustomerController.cs
public class CustomerController : ApiController { private List<Customer> customers; public CustomerController() { customers = new List<Customer>(); for (var i = 0; i < 3; i++) { customers.Add(new Customer { Id = i, FirstName = "First" + i, LastName = "Last" + i }); } } // GET: api/Customer public IEnumerable<Customer> Get() { return customers; } // GET: api/Customer/5 public Customer Get(int id) { return customers.FirstOrDefault(c => c.Id == i); } // POST: api/Customer public void Post(Customer customer) { } // PUT: api/Customer/5 public void Put(int id) { } // DELETE: api/Customer/5 public void Delete(int id) { } }
So the controller code is done and let’s wire up the controller into the OWIN pipeline by adding the HttpConfiguration to the OWIN start-up class which has the routing configuration.
Here is the complete start-up class code.
Startup.cs
public class Startup { public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); app.UseWebApi(config); app.UseWelcomePage(); } }
Lets do some quick tests in order to see if everything is working correctly. I am going to use the POSTMAN extension for Chrome and will execute following GET request.
/api/customer /api/cutomer/1
and with no surprises here is the result of 2 request.
As you can see it is fairly simple to set up OWIN and start using it in a Web api application. Moreover, there are 2 more ways to define the OWIN start-up class. First either you can decorate your with assemblu attribute as shown below
assembly: OwinStartup(typeof(OwinTestingDemo.Startup))]
or you can define it in your web.config as
<appSettings> <add key="owin:appStartup" value="OwinTestingDemo.Startup" /> </appSettings>
The choice of different startup may come handy in case for different environment you may want to run different middleware components.
That’s it for now and in the next post I am going to show how we can simplify testing web api with OWIN.
Securing Web API using Azure Part – 1: Simple Web Tokens
In this post I am going to talk about some of the nuances of securing web API using Azure and in order to keep my post short and sweet I am going to cover how to configure relying party and generating the SWT Token using Azure.
First I went and created a new ASP.NET Web API Project in Visual Studio 2013 and I am going to go my azure management portal to configure this newly created web application as a Relying Party. This configuration of Relying party is similar to my previous post Implementing Single Sign-On using Azure and I highly recommend to read it before you read this one.
Next I am going to add a service identity with username and password and the simple web token will be generated using this identity information for authentication.
Now we are going add our ASP.NET Web API Service as relying party as shown below.
As you can see above that I am using SWT as the token format and use the Windows Azure Access Control Service as my Identity Provider also we need to create a rule group so we click on “Rule groups” and add a description and save the rule.
Now we are going to map incoming claims to outgoing claims like we did in the previous post, except that instead of an Azure website it is an ASP.NET Web API Service.
As you can see above nothing special here all I am saying is that when an input identifier claims has a value of “ServiceUser” then we want to return “prashant.brall” to action claim value. This is done just for illustration purposes only and in real life application the claim mapping can be assigning a specific API Key per consumer so that this key is sent as part of the SWT token for additional verification purposes.
Now we are going to the “Application Integration” option of the Azure Access Control Service and going to use the OAuth WRAP (Web Resource Authorization Protocol) as shown below.
Lets put it all together and see the SWT Token live in action and instead of writing a program to test I am going to use Fiddler as I really like to see what is going across the wire at the raw http post level.
and this is how the SWT Token looks like when I open in notepad.
As you can see I have highlighted the return claim value as “prashant.brall” and some returned encrypted token which we will cover in the next post. Also below is raw http post using Fiddler in case you want to use in your own Access Control Service.
Content-Type: application/x-www-form-urlencoded
Host: prashantbrall.accesscontrol.windows.net
Content-Length: 95
Expect: 100-continue
Connection: Keep-Alive
wrap_name=ServiceUser&wrap_password=*********&wrap_scope=http%3a%2f%2flocalhost%3a51388%2f