Web API Tutorials Part 4 : Controller Attribute Based Routing

Route

Web API offers some powerful routing behaviour.  Let’s look at how we can use this in our app to avoid needing a new Controller for every Translation we wish to offer (again, ignore the fact our sample is likely only ever to require two way!).

We currently have a single AlphabetToMorseController with our old ITranslator implementation.  In the previous tutorial we abstracted our service into an extensible dictionary, this should allow us to take our Translator Key as a routing parameter and our string to translate as a parameter in the URI on our API.

Outcome

By the end of the post we’ll have refactored the existing AlphabetToMorseController to a generic TranslatorController, with our ITranslatorService being injected.  The Key will be provided through a Web API Route, and the Get Requested to the Controller will return a collection of available Translators.

Implementation

ITranslatorService

Let’s start by adding our ITranslatorService to our IoC container.  We’ll need to use an implementation factory to give the container some instruction regarding how to compose our instance.  The method signature for our AddSingleton looks like:

[csharp]
IServiceCollection.AddSingleton<ITranslatorService>(Func<IServiceProvider, ITranslatorService> implementationFactory);
[/csharp]

…which means we need to pass in a method taking an IServiceProvider as input, and our ITranslatorService as output, let’s create that and register it…

[csharp]
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();

services.AddSingleton<ITranslatorService>(ConfigureITranslatorService);
}

private ITranslatorService ConfigureITranslatorService(IServiceProvider serviceProvider)
{
var translatorService = new TranslatorService();

translatorService.AddTranslator("AlphabetToMorse", new AlphabetToMorseTranslator());
translatorService.AddTranslator("MorseToAlphabet", new MorseToAlphabetTranslator());

return translatorService;
}
[/csharp]

The service provider gives us access to other previously registered classes, enabling the factory to create instances with other dependencies.  It’s worth noting that our dependencies get lazy loaded, the factory method won’t get called until an instance is requested from the container.

Get()

We can now return something meaningful from the Get() method.  The Get method is generally used to return a collection of Id’s that can then be further interrogated via the API.  We’ll be returning a collection of all registered translators.

Change the ITranslator to an instance of ITranslatorService, and pull out the list of TranslatorKeys and return it as an array.

[csharp]
[FromServices]
public ITranslatorService _translatorService { get; set; }

// GET: api/values
[HttpGet]
public IEnumerable<string> Get()
{
return _translatorService.TranslatorKeys.ToArray();
}
[/csharp]

Get(translator, input)

Our controller is becoming agnostic to translator implementation.  Rename it TranslatorController, then we can start looking at using routing to specify our translator.

we need to change our Get Instance request routing using the Attribute previously specified.  We want it to take a translator, and our previous input.

[csharp]
[HttpGet("{translatorKey}/{input}")]
public string Get(string translatorKey, [FromUri] string input)
{
return _translatorService.Translate(translatorKey, input);
}
[/csharp]

We’ve defined a custom route for our Get Attribute, such that we can now query it using a uri in the form: /api/translator/AlphabetToMorse/inputstring.

We can now query our Translators:

Translators
Translators

…and query a translator:

Input String Translation
Input String Translation

Summary

Where are we?

  • We have a fully functional translator Web API.

Where are we heading?

  • Deploy to Azure;
  • Consuming our new Endpoint from our UWP app;
  • Implementing a LiveTileUpdate;
  • Making the app User Experience (UX) more friendly.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s