RenderSteps(expands, input));
}
IList RenderSteps(string[] expands, EditScriptDto input)
{
ExpandsUtility.AssertEmpty("Steps", expands);
return (input.Steps ?? Enumerable.Empty())
.Select(StepModel.CreateFrom)
.OrderBy(model => model.OrderNumber).ToList();
}
In this case we are using Expand to avoid the cost of expanding a large collection (the steps for a testscript/test case) which is part of the Script aggregate (believe it or not, there are testers out there writing tests scripts with 300+ steps...).
Controllers
Within our API controllers we just call the mapping method and pass in the expands parameter:
var script = _scriptReportingService.GetScript(id);
var wrapped = _viewModelMapper.Map(script, Expands);
return Request.CreateResponse(HttpStatusCode.OK, wrapped);
The Expands property in this case just exposed a property associated with the current request.
protected virtual string[] Expands
{
get { return (string[]) (Request.Properties["expand"] ?? new string[] {}); }
}
And this request property was captured by a simple DelegatingHandler that would parse the query string for various OData parameters - this approach made it a bit easier for other delegating handlers to have access to this information prior to the controller's methods being invoked.
OData support in ASP.Net Web API
For those who have been working with the various releases of ASP.Net WEB API since it was originally targeting WCF, there have been quite a few breaking changes along the way, including OData - which was introduced initially as a basic [Queryable] attribute that could be added to controller methods, and then later on, removed entirely pending a new OData re-implementation.
Recently the Web API team have announced greatly improved support for OData in the WebAPI - allowing the construction of entirely OData compliant services, as a preview release on nuget - the [Queryable] attribute is also back.
I believe this now includes support for $expand, which was previously missing, but I haven't yet had a chance to play with the latest release to confirm this - but I'm not entirely sure if this would have worked for our approach at any rate.
Next
Next, in part 3 of this series we take a look at how we generated API documentation.
" />
RenderSteps(expands, input));
}
IList RenderSteps(string[] expands, EditScriptDto input)
{
ExpandsUtility.AssertEmpty("Steps", expands);
return (input.Steps ?? Enumerable.Empty())
.Select(StepModel.CreateFrom)
.OrderBy(model => model.OrderNumber).ToList();
}
In this case we are using Expand to avoid the cost of expanding a large collection (the steps for a testscript/test case) which is part of the Script aggregate (believe it or not, there are testers out there writing tests scripts with 300+ steps...).
Controllers
Within our API controllers we just call the mapping method and pass in the expands parameter:
var script = _scriptReportingService.GetScript(id);
var wrapped = _viewModelMapper.Map(script, Expands);
return Request.CreateResponse(HttpStatusCode.OK, wrapped);
The Expands property in this case just exposed a property associated with the current request.
protected virtual string[] Expands
{
get { return (string[]) (Request.Properties["expand"] ?? new string[] {}); }
}
And this request property was captured by a simple DelegatingHandler that would parse the query string for various OData parameters - this approach made it a bit easier for other delegating handlers to have access to this information prior to the controller's methods being invoked.
OData support in ASP.Net Web API
For those who have been working with the various releases of ASP.Net WEB API since it was originally targeting WCF, there have been quite a few breaking changes along the way, including OData - which was introduced initially as a basic [Queryable] attribute that could be added to controller methods, and then later on, removed entirely pending a new OData re-implementation.
Recently the Web API team have announced greatly improved support for OData in the WebAPI - allowing the construction of entirely OData compliant services, as a preview release on nuget - the [Queryable] attribute is also back.
I believe this now includes support for $expand, which was previously missing, but I haven't yet had a chance to play with the latest release to confirm this - but I'm not entirely sure if this would have worked for our approach at any rate.
Next
Next, in part 3 of this series we take a look at how we generated API documentation.
" />

Expand implementation and view model mapping

What is Expand

Round-trips are the death of performance in many cases, and this is no different for API's.

The web does scale out well - so there is certainly the option to make lots of simultaneous requests, but this does not take care of the problem of addressing those related resources - if the you need to fetch back a resource's representation before you can construct additional requests to fetch other resources, you still are faced with the issues of latency.

Notice that we advertise the available expansions as a property of the resource - this is a feature of the Atlassian Jira API we adopted (and this list changes based on what expansions have already been applied).

Building a mapper

To allow expansion to be done correctly and at any depth, we needed to hand over construction of our view models to a third party - thus enters the view model mapper:

The implementation of this interface comprises a service where you can register:

Constructors - which are able to take a DTO/domain class/Tuple/whatever and construct a view model from it.

Expanders - a named expansion attached to a constructor

Map methods for mapping an instance to a view model, with a set of expansions to apply

Handling of special cases such as translating the results of a search to a suitable form for then translating into a view model

Given the plugin architecture used within the application, this provided the ability for plugins to add new Expand options to existing resources - so for example if a customer has the automated testing plugin enabled, then the script packages (folder) will also support expansions for the "AutomatedTests" collection of automated tests within that package.

As an example how we register an expander - here is code to register the expansion for a collection of steps associated with a script.

In this case we are using Expand to avoid the cost of expanding a large collection (the steps for a testscript/test case) which is part of the Script aggregate (believe it or not, there are testers out there writing tests scripts with 300+ steps...).

Controllers

Within our API controllers we just call the mapping method and pass in the expands parameter:

And this request property was captured by a simple DelegatingHandler that would parse the query string for various OData parameters - this approach made it a bit easier for other delegating handlers to have access to this information prior to the controller's methods being invoked.

OData support in ASP.Net Web API

For those who have been working with the various releases of ASP.Net WEB API since it was originally targeting WCF, there have been quite a few breaking changes along the way, including OData - which was introduced initially as a basic [Queryable] attribute that could be added to controller methods, and then later on, removed entirely pending a new OData re-implementation.

I believe this now includes support for $expand, which was previously missing, but I haven't yet had a chance to play with the latest release to confirm this - but I'm not entirely sure if this would have worked for our approach at any rate.