Alexa.NET.RequestHandlers 4.1.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Alexa.NET.RequestHandlers --version 4.1.1                
NuGet\Install-Package Alexa.NET.RequestHandlers -Version 4.1.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Alexa.NET.RequestHandlers" Version="4.1.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Alexa.NET.RequestHandlers --version 4.1.1                
#r "nuget: Alexa.NET.RequestHandlers, 4.1.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Alexa.NET.RequestHandlers as a Cake Addin
#addin nuget:?package=Alexa.NET.RequestHandlers&version=4.1.1

// Install Alexa.NET.RequestHandlers as a Cake Tool
#tool nuget:?package=Alexa.NET.RequestHandlers&version=4.1.1                

Alexa.NET.RequestHandlers

Alexa skills can get large and complicated and editing long switch statements can be error prone. This library allows you to isolate functionality into RequestHandlers. A request handler is an isolated piece of logic that you want your alexa skill to run based on a particular condition (it's a launch request, it's a specific type of intent, its the fallbackintent and the user has an account linked etc.).

So what is a request handler?

From a code point of view it's any class that implements the following interface

public interface IAlexaRequestHandler
{
	bool CanHandle(AlexaRequestInformation information);
	Task<SkillResponse> Handle(AlexaRequestInformation information);
}

The way this works is that when brought together in a pipeline and a request is processed, each of the request handlers has its CanHandle method executed in declaration order. The first handler that returns true is selected, and the handler logic in the Handle method is executed to generated the skill response.

Here's a couple of examples of a request handler

public class LaunchRequestHandler:IAlexaRequestHandler
{
    public bool CanHandle(AlexaRequestInformation information)
    {
        return information.SkillRequest.Request is LaunchRequest;
    }

    public Task<SkillResponse> Handle(AlexaRequestInformation<TSkillRequest> information){
        return ResponseBuilder.Ask("hello, what should I call you?");
    }
}
public class AnswerIntentRequestHandler:IAlexaRequestHandler
{
    public bool CanHandle(AlexaRequestInformation information)
    {
        return information.SkillRequest.Request is IntentRequest intent
        && intent.Intent.Name == "answer";
    }

    public Task<SkillResponse> Handle(AlexaRequestInformation<TSkillRequest> information)
    {
        var intentRequest = information.SkillRequest.Request as IntentRequest;
        return ResponseBuilder.Ask($"hello {intentRequest.Intent.Slots["answer"].Value}");
    }
}

Executing your request handlers

To execute your request handlers you build an AlexaRequestPipeline and register each of your RequestHanders. As we've said order here is important - it will allow you to make handlers that deal with subtle differences in functionality and you can register the most specific first (such as the two buy handlers in the example below).

var pipeline = new AlexaRequestPipeline(
    new[]{
        new LaunchHandler(),
        new BuySpecificProductHandler(),
        new BuyRequestHandler(),
        new IntentHandler(),
        new FallbackHandler()
    }
)

return await pipeline.Process(skillRequest, context);

Side note - another advantage of having handlers perform logic is that your executing environment doesn't need to know about the logic its executing, functionality can be tweaked and reordered by the order of the handlers without any alterations to the project that handles the Alexa requests.

Pre-packaged handlers

Although you can create handlers for yourself if you wish, there are several types of handler already available as base classes.

  • LaunchRequestHandler - CanHandle set up to look for launch requests
  • IntentNameRequestHandler - takes a constructor parameter of the intent name and returns true on an exact match
  • AlwaysTrueRequestHandler - Good as a final item in the list, a catch all that always returns true to ensure you never have requests fail without some handled response

(all these have a synchronous version that doesn't require await/async functionality)

What is the AlexaRequestInformation object in the interface?

The AlexaRequestInformation object is several pieces of information about the execution.

  • SkillRequest - the request being processed
  • Context - the context object passed in as part of the process call, useful for information from the executing request
  • Items - a dictionary of objects specific to this request, useful for passing information from interpreters

Custom Skill requests objects

It may be that you're using a sub-class of the SkillRequest object, for example skills that are APL enabled will be using the APLSkillRequest to get display specific info. In those cases there is a version of both the pipeline and each of the base classes that allows a version of the skill request to be specific, such as LaunchRequestHandler<APLSkillRequest>

Using error handlers

As well as handlers for requests, you can also register error handlers. These work in a similar way to RequestHandlers, allowing for specific request/exception combinations to be handled regardless of which of your handlers generated the exception in question. These are registered as an optional second argument in the pipeline constructor.

public interface IAlexaErrorHandler
{
    bool CanHandle(AlexaRequestInformation information, Exception exception);
    Task<SkillResponse> Handle(AlexaRequestInformation information, Exception exception);      
}

Creating request interceptors

There are times where you want to write logic that is run regardless of which handler is selected. Potentially you could wrap this logic around the pipeline, but that would require alteration of the execution environment. So instead you have request and error interceptors.

Interceptors have a single method, which are aware of the AlexaSkillInformation object. As multiple interceptors can be registered it passes in one more argument - the next item in the chain.

public interface IAlexaRequestInterceptor
{
    Task<SkillResponse> Intercept(AlexaRequestInformation information, RequestInterceptorCall next);
}

So for example you could have a request interceptor that executes a stopwatch, and stops just before returning the SkillResponse object to the user to see how long handlers run for:

public class TimingHandlerInterceptor : IAlexaRequestInterceptor<SkillRequest>
{
    public async Task<SkillResponse> Intercept(AlexaRequestInformation<SkillRequest> information, RequestInterceptorCall<SkillRequest> next)
    {
        var stopwatch = new Stopwatch();
        try
        {
            stopwatch.Start();
            return await next(information);
       }
        finally
        {
            stopwatch.Stop();
        }
    }
}

Handler aware interceptors

You also have situations where you want logic to occur under specific conditions - dependent on the handler selected, but ideally this should be kept isolated from the handlers themselves. To allow for this there is a handler aware request interceptor, which implements a second method which should be used instead.

Task<SkillResponse> Intercept(AlexaRequestInformation information, IAlexaRequestHandler handler, RequestInterceptorCall next);

The handler is passed in to help with logic you do not need to execute the handler yourself All the interceptor has to do is execute the next argument with the parameters - when the full chain is executed the next parameter will execute the handler as the last step in the chain.

If you want to pass information outside of the interceptor without altering the handler directly (as that would tightly couple your handler to your interceptor) then you can use the AlexaSkillInformation.Items dictionary.

public Task<SkillResponse> Intercept(AlexaRequestInformation<SkillRequest> information, IAlexaRequestHandler<SkillRequest> handler, RequestInterceptorCall<SkillRequest> next)
{
    if (handler is PurchaseHandlerBaseClass)
    {
        var productCatalog = GetProductData();
        information.Items.Add("productData", productCatalog);
    }

    return next(information);
}
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Alexa.NET.RequestHandlers:

Package Downloads
Alexa.NET.Annotations

Library to help make writing your first Alexa skill smaller and easier

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
4.2.0 8,945 8/16/2020
4.1.1 2,319 8/15/2019
4.1.0 596 8/9/2019
4.0.0 675 7/15/2019
3.1.0 1,313 12/21/2018
3.0.5 912 10/11/2018
3.0.0 870 10/1/2018
2.4.0 930 8/22/2018
2.0.0 1,022 8/9/2018
1.0.13 1,050 6/21/2018
1.0.12 1,008 6/21/2018
1.0.11 1,090 5/20/2018
1.0.5 1,013 5/19/2018
1.0.1 1,114 5/13/2018

Update to NetStandard2.0