Saturday, December 21, 2013

ASP.NET Web API 2 - Responding to Errors

ASP.NET Web API allows us to create HTTP services. These services are used by interested clients. We might run into several situations which might be unexpected ones. They might be because of client's input data or an uneventful situation on the service side. In these cases, we need to provide client with the relevant error information. In the previous post, we touched upon this area, where we discussed various types of responses from Web API. It seems better to further investigate this area.



Let us first have a look at how Web API life cycle explains how it handles the error. This is an excerpt from the official poster. The poster can be downloaded form Microsoft's download center.



From the message life cycle, it is quite clear that Exceptions generated during the execution of controller's requested action is passed through Exception filter which generates an Error Response.

Providing Error Details to Clients
When an error is generated for a client's request, ASP.NET Web API returns the information to the requester. So an external client would see the following in response of his request.



The API supports pushing additional details to the client. The is configured in HttpConfiguration used by the service. Here we can select an appropriate value for IncludeErrorDetails property of the configuration object. This is specially useful in debugging and test environments where we need to know what went wrong when an error is received as a result of client's request. In production environments this would rarely be the case as we don't want to expose these details (including stack trace) to our clients. This is because this doesn't help him, in any way, understanding the problem better. This might also leak service implementation to the users jeopardizing the security implementation.



Exception Filters
It must be remembered that the response pipeline has a special handling for HttpResponseException. This type of exceptions don't flow through the exception filter. The same is true for error response created using Request.CreateErrorResponse() in ApiController. These two cases wouldn't be handled by any external error handling APIs and frameworks including ELMAH. This is because of manual creation of a customized response that the application wants to push to client. The generated response shouldn't be tampered by any framework stages.

ASP.NET Web API supports exception filters to respond to cases of exceptions. It supports a specialized IFilter for exceptions, IExceptionFilter. We need to provide our customized ExceptionFilter to handle these exceptions.



Here IFilter interface is a special interface. ASP.NET Web Api has filters in other areas as well. All of these filters are defined in System.Web.Http.Filters namespace. All of these specialized interfaces inherit from this base interface. Be ready to see this interface in a number of future posts.



Let's introduce a brand new customized Exception type. We are planning to throw this exception when a client provides student information to request further data. In the cases where there is no corresponding student for the specified StudentId, we can throw this exception.


We can now introduce a new ExceptionFilter to handle this exception type. Let's name it as StudentNotFoundExceptionFilterAttribute. Yes I am also one of those who like big meaningful names ;). We can just inherit from ExceptionFilterAttribute type provided by ASP.NET Web API and provide the definition of OnException method as follows:


ASP.NET Web API supports the application of these filters on the scopes of action, controller and global. If we need this filter to be used for certain actions, we can decorate the actions with the filter. For the cases, where all actions should use a specific filter for exception situation, we can apply the filter on controller level. A service might also have a number of controllers. If we need the same filter to be used by all the controllers, we might apply the filter on global level.



A global exception filter is configured in the HttpConfiguration. The configuration has a Filters collection. The collection supports filters implementing IFilter interface.



Let's update InstituteController adding the following action to the controller. Here we are throwing the StudentNotFoundException when client passes a StudentId of a non-existent user.


Here we are sending such a request. Just look at the response, here the exception filter is being correctly applied. We can verify the exact error message we specified for the response in such cases.



As recommended on MSDN, you might want to add the same ExceptionFilterAttribute in GlobalConfiguration. For ASP.NET Web API, this can be added in FilterConfig. This also compiles fine but as we run it, the application fails with InvalidOperationException. When we look at the details of the exception, it doesn't really make sense. This is because we know that the attribute inherits from ExceptionFilterAttribute, which does implement IExceptionFilter interface.



But the message is right. Although it implements IExceptionFilter interface, it doesn't implement the one expected by the filter collection here.



Overriding Exception Filters From Wider Scope
As we just discussed, we can apply exception filters on action, controller and global levels. When an action execution causes an exception to be thrown, all filters in the processing chain are execution in the sequence of action, controller and then global filters. The filters are on the same level are executed in the sequence that they are defined. If an exception has been handled on a lower level, we might not want to bubble up the exception to the filters defined at a higher level. ASP.NET Web API2 has provided an option to override the filters at wider scopes. This can be achieved by OverrideExceptionFiltersAttribute. The type is sealed, an implementations of IOverrideFilter interface.



As you can notice above, there are also other implementations of the same interface to be used with action, authentication and authorization filters. Let us concentrate on exception filters for now. Let us introduce a global exception filter to be used for all exceptions. But we don't want this to be used if a controller or action itself has defined handlers for an exception.


Now let us add the filter to HttpConfiguration for the whole Web API on a global level. Let us update controller's action providing explicit details of exception filters to use the attribute to override any handling of exceptions in the pipeline on a higher level.



Based on our theory described above, when an exception is thrown from this action, ServiceExceptionFilterAttribute should not be used, as it added on global level. So the HTTP response provided on StudentNotFoundExceptionFilterAttribute should be used. We can verify this by viewing the request in Fiddler, it should still generate the same response as above, no matter we have a handler on a global level, as the one on the global level should have been overridden and not used by the framework.



HttpResponseException and its Special Handling
As we discussed above, HttpResponseException is a specialized Exception type introduced with ASP.NET Web API. This exception has a spcialized handling by the framework. It doesn't cause exception filters to be used by the framework. The definition of type can be seen as the following:



Now let us see how we can use HttpResponseException. Here we are creating an HttpResponseMessage and building up an HttpResponseException instance. We are throwing this exception when we can't find a student identified by the StudentId provided by the client. The interesting part is that the action is decorated with an exception filter. In a general case of any other exception type, this exception filter would be used to build up a response in case of an exception. In this particular case, since HttpResponseException already holds an HttpResponseMessage, it doesn't seem a need to build up another response, which is exactly what is happening, and exception filter shouldn't be used.


Here CreateErrorResponse is one of a list of extension methods for HttpRequestMessage type introduced in System.Net.Http namespace in System.Web.Http assembly. For a web client, the details of the exception can be provided and displayed as follows:



This looks very limited information is provided to the client. Our client can be interested in seeing more details to the actual cause of the problem. In order to do that the API has provided a new type, called HttpError. The definition of the type is as follows:



Now let's update the response to include some details to the error info returned to the client. This is extremely useful for the requesting client to determine the actual cause of the problem.


The idea is to add a list of details (key / value pairs) to an HttpError instance, and then use this to build up an HttpResponseMesssage. The response is formatted based on the Accepts header of client's HTTP request.



There are following values of keys defined in HttpErrorKeys type in System.Web.Http. They are used for standard errors. As the type required for the keys for this Dictionary [HttpError], they are all of string type.



Errors generated due to application of constraints
The services implemented with ASP.NET Web API also return error responses based on the failing route constraints. Here is an example action to return the courses attended by a particular student. The example is using alpha constraint.


All ASP.NET Web API route constraints implement IHttpRouteConstraint interface. AlphaRouteConstraint is a special type of RegexRouteConstraint where the patter is already prefixed.



All the default route constraints are available in System.Web.Http.Routing.Constraints namespace in System.Web.Http assembly. Here is a list of all default constraints available in the namespace.



A failing constraint just means that invalid route. Since this is a REST based service resources are identified and requested based on URIs. This means that a resource has been requested with some URI for which there is no resource / action is available. Hence this is an invalid request resulting in 404 message as follows:



We can also implement our custom route constraints. Here is a sample route constraint, named Max100Constraint. This constraint ensures a fixed 100 as the max value. Since we already have a MaxRouteConstraint providing a check on maximum values, we can just use extend it providing a fixed maximum value in base class constructor. We need to provide the details of the new constructor to the HttpConfiguration. It uses an implementation of IInlineConstraintResolver to provide the details of these constraints. The API provides a default implementation of the interface. We can just add the new route constraint to the default implementation.



Now we can use the constraint as we are using any default route constraint. We need to make sure that the identifier used to identify the constraint for route definition must match the key used to register it with IInlineConstraintResolver.



Now for all courseIds > 100, the service would result a 404 - NOT FOUND response.

Model Binding Errors
In the above description, we determined how we can verify routes based on registered constraints. We also saw how values from routes are copied to action parameters. They are simply copied based on their location in the route description to the action parameter identified by their name. Now let's take it a little further, HTTP supports clients to post data. The data can be posted using query parameters or request's content. This data can be received by ASP.NET Web API Service. The assignment of the data to the action parameters. Assignment of this data to action parameters is called Model Binding.

ASP.NET Web API looks for the action parameters in the client request. The data can be picked up from two places, query URL and request content based on that it is a simple or complex type. By default, simple types are picked up form request URL and complex types are from the content. We can validate this model as received from clients. The validation can fail and result in errors. The API has included following types for providing details of the errors on the service side.



In order to determine the model binding errors, ApiController has a ModelState property. This is of type ModelStateDictionary. We can access this from action's code to determine the validation results for the data passed with request.



We have been using data for Student type to be passed to the service. Let's update the type and introduce Data Annotation attributes for validation. Here we are using Range and Required field validation for StudentId and StudentName properties respectively.


Now let's prepare a post request in Fiddler and pass invalid student data to the service [StudentId = -1 with missing StudentName] as follows:



Obviously, the request would fail the validation requirement specified for our model. Let's try to see how ApiController.ModelState property shows this validation failure. Using the IsValid property, we can verify that model is not valid. The other details of the failure can be used to build up a response to be returned to the client.



We can also use an IActionFilter to filter the request before action code is executed. This can keep the action's code clean as we will not put any code to check if model is valid. This is a special case for interface type IFilter. Like IExceptionFilter (described above), this can also be used on action, controller or global scope. As is apparent from the request pipeline, action filters are executed after model binding. So by the time, they are invoked by the framework, the validation results are already in.

If we look at the definition of ActionFilterAttribute, there are two virtual methods. They are invoked at particular stages of message pipeline in ASP.NET Web API service. Actually, action execution is sandwiched between these two methods. The particular method we are interesting in, is OnActionExecuting(). This method is invoked by the framework before an action is executed for which this filter is enabled.



We can use the HttpActionContext argument in OnActionExecuting() method to determine the results of model validation. It is also possible to short-circuit the processing and generating a response from here without ever invoking the intended action, which is quite useful for model validation failures to generate an appropriate error response. Here we are creating an error response based on model validation results.


We can add action filters to ASP.NET Web API in the same way as an exception filter. Here we are decorating an action with the action filter attribute defined above.



Now an invalid request would result in a response with error details as follows:



What would happen if we throw an exception from action filter? From the official message pipeline it is not very apparent if ExceptionFilter (s) would be used for an exception thrown during execution of Action filters before action execution. Actually, if an exception is thrown from Action filters, the framework still uses the configured exception filters.

Download



Saturday, December 14, 2013

ASP.NET Web API 2 - Action's Response and IHttpActionResult

This is a continuation of our discussion about ASP.NET Web API. In this post we are trying to understand how results generated by actions are interpreted and further processed by ASP.NET Web API message pipeline. In the previous posts, we have defined various actions with three different types of returned data. There are following return types you might see for Web API action implementations:
  1. HttpResponseMessage
  2. IHttpActionResult [ASP.NET Web API 2]
  3. Any other type
  4. void
Every ASP.NET Web Api requests passes through a pipeline before a particular controller's action is invoked. The action's response can also be processed and passed through various stages before it is pushed to the requester. This is also possible that all the formatting is done at the action's side generating an HttpResponseMessage, resulting in bypassing all these stages. At the end, irrespective of returned data, an HttpResponseMessage is generated.



ASP.NET Web API message life cycle poster can be obtained from Microsoft's download center. If you understand the flow of message as described in this poster then you understand it all. So make sure that all the particular pieces are looked at with great emphasis and care.



Return type as void
These are the simplest of all actions from development perspective. They are specially useful for the requests with HTTP verbs including PUT / DELETE and POST. In these cases, the client is not interested in the data returned form the service. They are for pushing data to the service. Let's just make sure that having a return type as void doesn't mean nothing is being returned to the client and still an HttpResponseMessage is generated.

Returning Domain Object
This is the simplest and easiest of all options. Here we treat our actions invocations as regular methods calls. We return domain objects from these actions. In this way, our actions' code is not populated with the HTTP based types. It is the framework's responsibility to create an HTTP response including the returned data as value.


It is for these actions, that framework hooks up the injected MediaTypeFormatter (s) and Content Negotiators based on the media types requested by client and type of data being returned. After data is passed through these stages, an HttpResponseMessage is generated and returned to the client.

Returning HttpResponseMessage Directly
This is another option allowed for Web API actions. Here the API takes the responsibility for creating the response on its own making it easier for the framework handling the response message. As a developer, we have the flexibility for controlling the HttpStatusCode generated with the response.


As you can see here, in addition to the data, we are specifying the HttpStatusCode for the returned response. We are using the value OK (= 200).

IHttpActionResult Interface & ASP.NET Web API 2
Here we are neither generating the domain objects directly nor we are handcrafting the HttpResponseMessage directly in ApiController's actions in a synchronous fashion. Instead, we are returning a response held by a type implementing IHttpActionResult interface. ASP.NET Web API 2 introduced IHttpActionResult in order to support asynchronous generation of HttpResponseMessage.



It also introduced a number of implementations of the interface in System.Web.Http.Results namespace in System.Web.Http assembly.



ApiController has also been updated with a number of additional methods returning such results. They make it easier for generating the response. They also include the appropriate HttpStatusCode with the response based on the method being used. These methods are supposed to be used from ApiController's actions to generate a response. The value obtained from these methods can simply be returned by the controller's action method.



The following is an example action supporting HTTP Post method. The action accepts student's data from the request body. After writing the data to the console, it generates an HTTP OK for the requesting client.


Let us see how our service responds to a request invoking the above action. In order to keep the example simple, the action is not doing much other than just writing the student's data to the console. It is also generating an OKResult (implements IHttpActionResult) by calling the Ok() method defined in ApiController type.



We can also provide custom implementation of the interface and use them in Web Api actions.

Returning Errors
The actions with return type as void or any other type other than HttpResponseMessage has only one way to return an error response i.e. to throw an exception in the event. The exception is caught by the framework pipeline and an appropriate error response is generated.



On the other hand the actions returning HttpResponseMessage can always generate error responses. Here we are using Request property of ApiController. This is of type HttpRequestMessage.


If this is a web client, the error is displayed in the browser as follows:



For the actions returning IHttpActionResult, we can always return different implementations of the interface based on the underlying condition. In case of error we may also use the methods added in ApiController for such conditions.

Wednesday, December 11, 2013

ASP.NET Web API 2 Content Negotiation & Media Type Formatting

ASP.NET Web API supports requests using HTTP methods. These requests can use any HTTP method including (but not limited to) GET and POST methods. The data to / from the service can use any media type as long as the service is supporting those formats. The client requests can specify the media type format using Accepts or Content-Type details of HTTP message. In the previous posts we discussed how ASP.NET Web API uses content negotiation to provide data to clients based on the requested format. There are some default media type formatters in ASP.NET Web API 2.

All of these MediaTypeFormatter(s) are available in System.Net.Http.Formatting assembly except ODataMediaTypeFormatter, which is available in System.Web.Http.OData assembly. All of them inherit from MediaTypeFormatter abstract base type.



MediaTypeFormatter has two abstract members. These methods are used to determine if a particular type can be formatted using the particular formatter. The methods return true if they support so. Here CanReadType is used when the service receives a request with content type as passed in the argument. On the other hand, CanWriteType is used when some data is to be pushed to client. Again the argument would refer to the data type of the object being pushed to the client.



Here the Read and Write methods in MediaTypeFormatter are asynchronous. BufferedMediaTypeFormatter provides a synchronous wrapper around these methods.

Pipe Delimited Formatter
Let's assume that our service needs to supports providing and accepting students' data in pipe delimited format. Now we need to add support to understand how to parse Student's data when provided by a client. We also need to convert the data pushed to our clients into pipe delimited format. ASP.NET Web API supports formatting data using MediaTypeFormatters. There are two such formatters added by default. They are to support XML and JSON data. If we are planning to support a new format, we need to add an explicit MediaTypeFormatter for such purpose. Here is a simpleton formatter to support pipe delimited data.


As you can notice from the above definition, the same formatter is used to read and write data by the service. Each formatter can be used to support a number of media types. They are identified through SupportedMediaTypes collection in MediaTypeFormatter. Our formatter is supposed to support pipe delimited text data, so the supported media type is specified as "text/pdv".

We must know that the same formatter is used both for reading and writing data by our service. The decision for supported types can be done in CanReadType / CanWriteType method pair. They are from the perspective of our service. Here CanReadType will be used for GET based requests when we need to push data to clients. On the other hand CanWriteType is used when service accepts some data from a client. In order for actual reading and writing of data for these types ReadFromStream and WriteToStream methods are used respectively.

Now we need to add the custom formatter to the list of Media Type Formatters used by the service. This is part of HttpConfiguration for the service. We can update WebApiConfig as follows:



Requesting Data for Configured Media Type Format
In the earlier posts we have seen how we can use Fiddler to request Web API to provide data in the format of the specified media type. We just need to use Accepts header. Here we are specifying the media type as "text/pdv".



Posting Data in Configured Media Type Format
Since our MediaTypeFormatter supports reading Student data in text/pdv format, we can post data to the service in this format. Let us add an action in our InstituteController. The action supports POST method of HTTP. Since we are using Attribute routing, we need to specify the route on the action.


We can compose the request using Fiddler. Here we are posting student's data in Pipe delimited format to the service.



Based on the content type specified in the request, the service picks up the correct MediaTypeFormatter. Since we are supporting data for Student type, the provided data is parsed into Student type format using ReadFromStream method of the formatter. The parsed object is then passed to the requested action as follows:



Download



Sunday, December 8, 2013

Attribute Routing in ASP.NET Web API 2

In the previous post, we discussed about HTTP routing in ASP.NET Web API. With version 2, Microsoft has incorporated a more flexible version of routing into the API. This is called Attribute Routing. The feature is contributed to ASP.NET MVC project by Tim McCall [http://attributerouting.net/]. Conventional routing supports defining the routes on global level. Since attribute routing allows defining routes on controllers and their actions, it provides extraordinary flexibility in defining these routes. The feature can be used to define resource hierarchies in the same controller.It also enables us to define options parameters, default values and resource and parameter constraints.

Enabling Attribute Routing
Let's first create an ASP.NET Web API project. Let's name this project as InstituteService.



Attribute Routing is included in ASP.NET Web API 2. Visual Studio 2013 supports creating ASP.NET Web API 2 based projects out of the box. We can also create then in Visual Studio 2012 with the help of Microsoft.AspNet.WebApi.WebHost nuget package.



The service is required to provide information about students and their courses. Here we are introducing types Student and Course to hold information about students and courses respectively. Each course maintains a list of students attending the course.

We need to update Web API configuration to use Attribute routing. The configuration is done in WebApiConfig. The new version of ASP.NET Web API has introduced a new version in HttpConfiguration type with an extension method MapHttpAttributeRoutes. We need to update the code to use this method instead.



Now let us add an empty controller for our Institute service. Here we are creating it as an empty API Controller.



As we have discussed in previous posts, a Web API controller inherits from ApiController type from System.Web.Http.



Now let us seed some data which could be returned from the service. In order to keep the example simple, let us create some data in the service constructor. Here we are creating three students assigned to two different courses. The first course is assigned with all the three students when the second course is just being attended by Muhammad and Roosevelt.


Defining Routes Using [RoutePrefix] & [Route] Attributes
ASP.NET Web API 2 support defining routes by introducing RoutePrefix and Route attributes. The RoutePrefix attribute can be used on controllers. This allows definition of a default prefix for all the actions in the controller.


Now we can add relative routes to individual actions. The routes are defined on actions using [Route] attribute. Here we are adding two actions to provide the list of course and students of the institute.


The above actions can be used to fulfill client request as follows:



Parameterized Routes
In the previous post we discussed how parameterized routes can be used for Web API resources. For conventional routing only certain parameters can be used as part of the request routes. For any additional parameters, we had to use query parameters. Since attribute routes are defined on individual actions, we can use action parameters for parameterized routes. In the following example, we are using courseId as route parameter. This is one of the parameter of the action defined below:


The above action can be used with the following request. As you can notice, the client is requesting all the students attending course (CourseId = 2). This course is only being attended by Muhammad and Roosevelt.



Route Constraints
Attributes routes also supports constraints. The list of constraints can be found on msdn (route constraints). In the following example we are defining two actions. The first actions is providing the list of courses being attended by a student identified by StudentId parameter. In this case, the constraint is defined to check that the Id must be an integer value. This is achieved using int contraint. For the second action, the same can be requested using student's name as parameter. Here we are using alpha constraint. This is to make sure that the name only include alpha characters. The same can be achieved using regex constraint (commented).


Let's see how we can request the above resources. Here the service is returning the list of courses attended by Muhammad. As you can notice, the returned data also includes the list of all students attending the courses. You might want to create a different type to return the course data to clients.



ASP.NET Web API 2 also supports defining custom constraints. It provides IHttpRouteConstraint interface in System.Web.Http.Routing namespace. We need to provide definition for Match method of the interface. The constraint is considered passed when the method returns true.

Default Values for Optional Route Parameters
Web API 2 also supports optional route parameters. They are identified with a question mark followed by the parameter name. The parameters are still identified with the brackets (e.g. {studentId?}). The default values can be specified as a method parameter as we generally specify for optional parameters for a method. In the following example, we are defining an action with studentId as a optional route parameter. The default value for the parameter is 1, so it would be returning all the courses attended by Muhammad.


The other option to define default values is by including the default value as part of the route. In order to get the same behavior as above, we can define the route as follows:


Although the behavior seems to be same for the above two examples, but they are a little different in the way they work out the value for the optional parameter in case one is not specified in the client request. The first example just causes the action to be used in case the parameter is not specified, and the value for the parameter is through optional parameter for C# method. For the second example, ASP.NET Web API framework is responsible for assigning value for the parameter. This is done through the model binding process. We can also define our custom model binder but lets just keep it for some other post.

Versioning Resources
ASP.NET Web API 2 also makes it super easy for versioning the API. As we have discussed before we might not want to expose the list of students who are signed up for a particular course when we return the course attended by a particular student. Here we are just introducing a new type for holding courses with the details including Id and its name.


We can use this type to introduce a new version for such requests. Here we have just added a literal in our resource route url. We can use the same for all actions exposing the same version of types to our clients.


We can use the above action using the same route prefix as we define on the Api controller. Here we are using the same Api by exposing a different version of Course type to clients.



Overriding RoutePrefix for Actions
We have been discussing how we can define routes for Web API actions. The specified route on actions is used with the route prefix defined on controller level [RoutePrefix attribute]. What if we want to override the route on some of these actions. ASP.NET Web API 2 supports this. This is defined using tilde (~) character. In the following example, we are doing the same thing:


Now we don't need to use the route prefix defined on the controller. We can access the resource provided by the above as follows:



Route Order and Precendence
Since the routes are defined on the actions themselves, it is natural to wonder what would happen if there are multiple actions qualify for the same URL. This is very common when optional route parameters are used. In the following example we have two actions with actions annotated with independent routes overriding route prefixes.


Now which of these action would be used when we use the URL below. It seems that the first action is being used. But why?



As a matter of fact, there is a particular logic for route precedence for these actions. There are certain ASP.NET Web API rules in action. And these rules are being applied here causing the first action to be used for the request. So now we know why this is happening whatever is happening. But we are interested in knowing what these rules are. The following is copied from msdn.



So in the case of our example, since the first action is annotated with literal route, it is taking precedence on the route defined on the other action with parameterized route. As is apparent from the above rules, we can override this order by defining an explicit RouteOrder on the actions.


Now if we use the same URL, we are definitely hitting the second action as follows:



Download