Alexa.NET.RequestHandlers
4.1.1
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
<PackageReference Include="Alexa.NET.RequestHandlers" Version="4.1.1" />
paket add Alexa.NET.RequestHandlers --version 4.1.1
#r "nuget: Alexa.NET.RequestHandlers, 4.1.1"
// 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 | Versions 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. |
-
.NETStandard 2.0
- Alexa.NET (>= 1.8.1)
- Alexa.NET.StateManagement (>= 2.1.1)
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