Xamarin.Tip – Add Easter Eggs to UWP with Key Combos

In a previous post, I talked about adding easter eggs to your iOS and Android applications (using Xamarin.Forms or Xamarin Native) using the shake gesture – allowing us to execute it within the context of the current view we are in whether native or in forms, and then from there execute any bit of code we want!

Check that out here: Xamarin.Tip – Add Easter Eggs on Shake

In this post, I want to give an example of adding the same sort of functionality to your UWP applications. This again is usable whether in Xamarin.Forms or native UWP.

Since nearly all UWP devices are PC’s and not mobile devices, and often don’t have gyrometers, adding this type of feature using a shake gesture just doesn’t make sense. I propose, instead, to use key combos!

Tracking Key Combinations in UWP and Xamarin.Forms

In UWP there are two main things needed to track key combinations – the KeyState and the OnKeyUp method.

Accessing the current KeyState is as easy as:

CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);

Where VirtualKey.Control can be any key! In this case it is the Ctrl key.

In our UWP Page classes, we can also override the OnKeyUp method which is fired whenever any key is pressed. This means that in this method, we can check the KeyState of any number of keys, and also get the current key that was just pressed. Alternatively, you can do this in the OnKeyDown override depending on how you want it to behave.

Let’s look at a full example of this implemented where we want to fire some Easter Egg off once the Ctrl + E key combo is hit:

MainPage.xaml.cs

// NOTE: this is the UWP MainPage - not the Xamarin.Forms MainPage!
public sealed partial class MainPage
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    private static bool IsCtrlKeyPressed()
    {
        var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
        return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
    }

    protected async override void OnKeyUp(KeyRoutedEventArgs e)
    {
        base.OnKeyUp(e);
        if (IsCtrlKeyPressed())
        {
            if (e.Key == VirtualKey.E)
            {
                await EasterEggAsync();
            }
        }
    }

    /// <summary>
    /// Do something with an easter egg!
    /// </summary>
    /// <returns>The developer options async.</returns>
    private async Task EasterEggAsync()
    {
        // DO SOMETHING! 😀
        await DoAnEasterEggThing();
    }
}

Just like in our Android and iOS Shake examples, from here in UWP, we can get reference to our current Xamarin.Forms page and execute with some context by hitting (App.Current.MainPage as NavigationPage).CurrentPage assuming that the MainPage of our app is a NavigationPage.

In another post, we will look at combining these 3 platform methods to give ourselves as developers some tools to make our lives easier while debugging and testing!


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.


Advertisement

Alexa.Tip – How to Host Alexa Skills in Azure

If you’re a .NET developer in the Azure cloud sphere and want to start dabbling in Alexa Skill Development, you don’t have to uproot your entire career and development process to go learn AWS, how Lambdas work, the serverless lifecycle, etc. In this post, we’ll go over just how easy it can be to build an Alexa Skill using C#, ASP.NET Core, and Azure!

The traditional setup for Alexa Skills is:
– AWS Lambda
– .NET Core Lambda project template

But we’re going to be using:
– Azure App Services
– ASP.NET Core API project template

NOTE: This is not an introduction into how Alexa skills work, or how to create your very first skill. This is meant to provide options for hosting your skills, and for how to build skills in general using .NET. If you’re BRAND new to Alexa Skill development, start by reading through their documentation (mostly using node.js, but focus on the structure of an interaction model, what intents and slots are, etc.)

For source of the entire project checkout: https://github.com/SuavePirate/Alexa.NET.WebApi

Step 1 – Create an Alexa Developer Account

If you haven’t already created an Alexa Developer account, you’ll need one in order to register and test your skill.

Simply follow, the Amazon documentation on how to do this – super simple: https://developer.amazon.com/alexa

Step 2 – Create a Skill in the Developer Console

With your Alexa developer account, create a new Skill.

Choose Custom Skill:

create_skill

Then choose the empty “Start from Scratch” template:

choose_template

Now you can manage your interaction model.

For this example, we are going to create a skill that let’s users ask for information about Animals. We’ll use a custom Intent for this, but use the built in AMAZON.Animal slot.

On the left side, go to JSON Editor and paste this interaction model. You can make adjustments as you see fit:

interactionModel.json

{
  "interactionModel": {
    "languageModel": {
      "invocationName": "animal facts",
      "intents": [
        {
          "name": "AMAZON.FallbackIntent",
          "samples": []
        },
        {
          "name": "AMAZON.CancelIntent",
          "samples": [
            "I'm all set"
          ]
        },
        {
          "name": "AMAZON.HelpIntent",
          "samples": []
        },
        {
          "name": "AMAZON.StopIntent",
          "samples": [
            "Quit",
            "Goodbye"
          ]
        },
        {
          "name": "AnimalFactIntent",
          "slots": [
            {
              "name": "Animal",
              "type": "AMAZON.Animal"
            }
          ],
          "samples": [
            "I'd like to know about {Animal}",
            "What is an {Animal}",
            "Give me information about the {Animal}",
            "Tell me about {Animal}"
          ]
        }
      ],
      "types": []
    }
  }
}

This allows our users to ask things such as “Tell me about Monkeys” and then use the animal they are asking for to send information back to them!

Step 3 – Create the ASP.NET Core API

In Visual Studio, create a new project and choose the ASP.NET Core Web Application:

aspnetcore

In the next dialog, select the API template, and be sure that HTTPS is enabled:

API_project_with_https

With your new web application, you’ll need to install the Alexa.NET Nuget Package from Tim Heuer
https://www.nuget.org/packages/Alexa.NET/1.5.5-pre

This nuget package has models for the JSON that Alexa sends to your API and a convenient fluid API design for building your responses that is similar to how the actual Alexa Java and JavaScript SDKs work.

Now that the Alexa models are available, let’s create a new API controller:

AlexaController.cs

[Route("api/[controller]")]
public class AlexaController : Controller
{
    /// <summary>
    /// This is the entry point for the Alexa skill
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public SkillResponse HandleResponse([FromBody]SkillRequest input)
    {
        var requestType = input.GetRequestType();

        // return a welcome message
        if(requestType == typeof(LaunchRequest))
        {
            return ResponseBuilder.Ask("Welcome to animal facts, ask me about information on an animal", null);
        }

        // return information from an intent
        else if (requestType == typeof(IntentRequest))
        {
            // do some intent-based stuff
            var intentRequest = input.Request as IntentRequest;

            // check the name to determine what you should do
            if (intentRequest.Intent.Name.Equals("AnimalFactIntent"))
            {
                // get the slots
                var animal = intentRequest.Intent.Slots["Animal"].Value;
                if(animal == null)
                    return ResponseBuilder.Ask("You forgot to ask about an animal! Please try again.", null);

                return ResponseBuilder.Tell($"I would normally tell you facts about ${animal} but I'm not a real skill yet.");
            }
        }

        return ResponseBuilder.Ask("I didn't understand that, please try again!", null);
    }
}

This controller contains a single HTTP POST endpoint that takes in an SkillRequest. It then breaks down the request in order to respond accordingly. So if the user opens the skill which initiates the LaunchRequest, we can give them a welcome message with hints on what they can ask about. Then if they ask for information about an animal, we can handle the IntentRequest with the intent name of “AnimalFactIntent” and use the Animal slot value!

That’s all there is too it! I’d normally suggest abstracting this out of using the controller so that it is more easily testable with unit tests, but for the sake of a simple example, it will work fine.

Step 4 – Publish to Azure App Service

Now that we have our ASP.NET Core project, we need to publish it to an Azure App Service. You can do this directly in Visual Studio or in the Azure portal. For the sake of this example, we’ll do it directly in Visual Studio – assuming you have a valid Azure license and account setup.

From the Solution Explorer – right click your project and Select “Publish”.

Select the “App Service” option and click “Create”.

Then fill out the form to create a new App Service:
AzurePublish

Once your publish is done, you’ll need to ensure that HTTPS / SSL is configured correctly for your app service.

In the Azure portal, go to your new App Service, then scroll to the SSL Settings section.

Be sure that you enforce SSL (Alexa requires endpoints to use HTTPS with trusted certificates. The default App Service SSL cert is signed with Microsoft’s trusted certificate which means that Amazon will accept it).

azure_ssl.PNG

Now make sure that you can hit your App service API endpoint. I usually prefer to enable Swagger for my API using Swashbuckle for this: https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-2.1&tabs=visual-studio%2Cvisual-studio-xml

Step 5 – Register Endpoint with Alexa Skill

Now that we have our App Service with HTTPS set up, we need to go back to the Alexa Developer Console and to the skill. In the left menu, scroll down to the “Endpoint” option.

In the main view, select “HTTPS” instead of “AWS Lambda ARN”. Then enter the URL for the endpoint in your app service and choose the subdomain ssl cert option:
azure_alexa_endpoint

Once this is done, you can save, and build your skill then proceed to test it!

Step 6 – Test

In the Alexa Developer Console, go to your skill and select the “Test” tab. Here you can type or say things like “Open Animal Facts” or “Ask Animal Facts to tell me about Monkeys”.

animal skill test

Here you can also view the JSON that Alexa is sending to your skill and use that to test against your skill directly using something like Swagger or Postman.

Here’s an example JSON input you could use to test:

{
    "version": "1.0",
    "session": {
        "new": false,
        "sessionId": "...",
        "application": {
            "applicationId": "..."
        },
        "user": {
            "userId": "..."
        }
    },
    "context": {
        "AudioPlayer": {
            "playerActivity": "IDLE"
        },
        "Display": {
            "token": ""
        },
        "System": {
            "application": {
                "applicationId": "..."
            },
            "user": {
                "userId": "..."
            },
            "device": {
                "deviceId": "...",
                "supportedInterfaces": {
                    "AudioPlayer": {},
                    "Display": {
                        "templateVersion": "1.0",
                        "markupVersion": "1.0"
                    }
                }
            },
            "apiEndpoint": "https://api.amazonalexa.com",
            "apiAccessToken": "..."
        }
    },
    "request": {
        "type": "IntentRequest",
        "requestId": "...",
        "timestamp": "2018-09-04T17:07:45Z",
        "locale": "en-US",
        "intent": {
            "name": "AnimalFactIntent",
            "confirmationStatus": "NONE",
            "slots": {
                "Animal": {
                    "name": "Animal",
                    "value": "monkeys",
                    "confirmationStatus": "NONE"
                }
            }
        }
    }
}

You can also test on a real Alexa device! Once you enabled testing, any device that is assigned to the same email address as your Alexa Developer Account will have it enabled.

And that’s it! Now get out there and build some Alexa Skills in .NET!


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile and AI developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.


voicify_logo
I’m the Director and Principal Architect over at Voicify. Learn how you can use the Voice Experience Platform to bring your brand into the world of voice on Alexa, Google Assistant, Cortana, chat bots, and more: https://voicify.com/


Adding a File Upload Field to Your Swagger UI With Swashbuckle

If you’re building ASP.NET Core Web APIs, then I hope you’ve heard of Swashbuckle – the tool to generate the Swagger UI automatically for all of your controllers to make manual testing your endpoints visual and simple.

Out of the box, the documentation helps you set up your UI, handle different ways to authenticate (which we will touch on in a later post), and have it all hooked up to your controllers. However, this only handles the most common cases of required requests with query string parameters and HTTP Body content.

In this post, we’ll look at a quick and easy way to also add File upload fields for your API endpoints that consume IFormFile properties to make testing file uploading even easier.

Basic Swagger Setup

First thing’s first, install that puppy:

Package Manager : Install-Package Swashbuckle.AspNetCore
CLI : dotnet add package Swashbuckle.AspNetCore

Let’s first look at a simple swagger setup as our baseline before we add everything for our HTTP Header Field.

Startup.cs

//...
public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSwaggerGen(config =>
    {
        config.SwaggerDoc("v1", new Info { Title = "My API", Version = "V1" });
    });
    // ...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ...
    app.UseMvc();

    app.UseSwagger();
    app.UseSwaggerUI(config =>
    {
        config.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1");
    });
    // ...
}
//...

This setup gives us all we need for our basic UI and wireup to our controllers!
Running this gives us our basic swagger at /swagger:
Swagger no header

Adding a File Upload Field

What we have to do now is add an OperationFilter to our swagger generation. These OperationFilters can do a whole lot and enable us to customize the swagger document created which is what drives the fields and info on the UI.

Let’s start by creating our FormFileSwaggerFilter class.

FormFileSwaggerFilter.cs

/// <summary>
/// Filter to enable handling file upload in swagger
/// </summary>
public class FormFileSwaggerFilter : IOperationFilter
{
    private const string formDataMimeType = "multipart/form-data";
    private static readonly string[] formFilePropertyNames =
        typeof(IFormFile).GetTypeInfo().DeclaredProperties.Select(p => p.Name).ToArray();

    public void Apply(Operation operation, OperationFilterContext context)
    {
        var parameters = operation.Parameters;
        if (parameters == null || parameters.Count == 0) return;

        var formFileParameterNames = new List<string>();
        var formFileSubParameterNames = new List<string>();

        foreach (var actionParameter in context.ApiDescription.ActionDescriptor.Parameters)
        {
            var properties =
                actionParameter.ParameterType.GetProperties()
                    .Where(p => p.PropertyType == typeof(IFormFile))
                    .Select(p => p.Name)
                    .ToArray();

            if (properties.Length != 0)
            {
                formFileParameterNames.AddRange(properties);
                formFileSubParameterNames.AddRange(properties);
                continue;
            }

            if (actionParameter.ParameterType != typeof(IFormFile)) continue;
            formFileParameterNames.Add(actionParameter.Name);
        }

        if (!formFileParameterNames.Any()) return;

        var consumes = operation.Consumes;
        consumes.Clear();
        consumes.Add(formDataMimeType);

        foreach (var parameter in parameters.ToArray())
        {
            if (!(parameter is NonBodyParameter) || parameter.In != "formData") continue;

            if (formFileSubParameterNames.Any(p => parameter.Name.StartsWith(p + "."))
                || formFilePropertyNames.Contains(parameter.Name))
                parameters.Remove(parameter);
        }

        foreach (var formFileParameter in formFileParameterNames)
        {
            parameters.Add(new NonBodyParameter()
            {
                Name = formFileParameter,
                Type = "file",
                In = "formData"
            });
        }
    }
}

This operation filter takes the operation parameters, then uses reflection to find the type of the field. If the field is an IFormFile, then we add a new file field from the formData section to our parameters. This in turn will update our swagger definition json file, and when rendered adds the field to our UI.

This even works great with endpoints that take a separate HTTP Body, query parameters, and files!

Now we need to reference it in our Startup when we initialize swagger:

Startup.cs

//...
public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSwaggerGen(config =>
    {
        config.SwaggerDoc("v1", new Info { Title = "My API", Version = "V1" });

        config.OperationFilter<FormFileSwaggerFilter>();
    });
    // ...
}

Here’s an example controller with an endpoint that uses the file upload:

FileUploadController

[Route("api/[controller]")]
public class FileUploadController : Controller
{
    [HttpPost]
    public async Task<IActionResult> CreateMediaItem(string name, [FromForm]IFormFile file)
    {
        // Do something with the file
        return Ok();
    }
}

This controller ends up rendering in our Swagger UI as:
Fileupload_swagger

And using this, we can now submit our request with an uploaded file and all our other parameters!


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Adding a Required HTTP Header to Your Swagger UI With Swashbuckle

If you’re building ASP.NET Core Web APIs, then I hope you’ve heard of Swashbuckle – the tool to generate the Swagger UI automatically for all of your controllers to make manual testing your endpoints visual and simple.

Out of the box, the documentation helps you set up your UI, handle different ways to authenticate (which we will touch on in a later post), and have it all hooked up to your controllers. However, this only handles the most common cases of required requests with query string parameters and HTTP Body content.

In this post, we’ll look at a quick and easy way to also add fields for your custom HTTP Request Headers so you can fill them out while testing without having to do some funky stuff in the console.

Basic Swagger Setup

First thing’s first, install that puppy:

Package Manager : Install-Package Swashbuckle.AspNetCore
CLI : dotnet add package Swashbuckle.AspNetCore

Let’s first look at a simple swagger setup as our baseline before we add everything for our HTTP Header Field.

Startup.cs

//...
public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSwaggerGen(config =>
    {
        config.SwaggerDoc("v1", new Info { Title = "My API", Version = "V1" });
    });
    // ...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ...
    app.UseMvc();

    app.UseSwagger();
    app.UseSwaggerUI(config =>
    {
        config.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1");
    });
    // ...
}
//...

This setup gives us all we need for our basic UI and wireup to our controllers!
Running this gives us our basic swagger at /swagger:
Swagger no header

Adding Custom Headers

What we have to do now is add an OperationFilter to our swagger generation. These OperationFilters can do a whole lot and enable us to customize the swagger document created which is what drives the fields and info on the UI.

Let’s create a MyHeaderFilter and then add it to the AddSwaggerGen call.

MyHeaderFilter.cs

/// <summary>
/// Operation filter to add the requirement of the custom header
/// </summary>
public class MyHeaderFilter : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        if (operation.Parameters == null)
            operation.Parameters = new List<IParameter>();

        operation.Parameters.Add(new NonBodyParameter
        {
            Name = "MY-HEADER",
            In = "header",
            Type = "string",
            Required = true // set to false if this is optional
        });
    }
}

And now we need to update our Startup class:

Startup.cs

//...
public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSwaggerGen(config =>
    {
        config.SwaggerDoc("v1", new Info { Title = "My API", Version = "V1" });

        config.OperationFilter<MyHeaderFilter>();
    });
    // ...
}

Now when we run and navigate to our /swagger url, we can see:
Swagger with header

When we fill out that field, we can now pull the value off the request header in our controller!

ContentController.cs

[Route("api/[controller]")]
public class ContentController : Controller
{
    public void Search([FromBody]InputModel model)
    {
        Console.WriteLine(Request.Headers["MY-HEADER"]);        
    }
}

In further posts, we’ll talk about adding Bearer Authentication, XML Comments, and More 🙂


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Add Model Validation to Your ASP.NET Core Web API

If you’re used to creating traditional Web APIs in ASP.NET, you’ve probably become accustom to using System.ComponentModel.DataAnnotations such as the [Required] or [StringLength] data attributes. Using these in your models that are parameters to your API project would return the proper 400 response code when the input didn’t match the requirement.

In ASP.NET Core 2.0, this is no longer built in right out of the box, but setting it up is super easy! So if you don’t want to abstract your model validation in your business logic layer and want to get it out of the way right away when the request comes in, check this out.

There are only two steps to doing this:

  • Create an implementation of `IActionFilter`
  • Register this Filter class in your startup

Let’s start by creating a ValidatorActionFilter class:

ValidatorActionFilter.cs

/// <summary>
/// Filter for returning a result if the given model to a controller does not pass validation
/// </summary>
public class ValidatorActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!filterContext.ModelState.IsValid)
        {
            filterContext.Result = new BadRequestObjectResult(filterContext.ModelState);
        }
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {

    }
}

What this does is check the current HttpContext.ModelState to make sure it is valid. This allows us to ensure we don’t have to make this check in each endpoint. Note, we don’t have to add anything in the OnActionExecuted method since this filter is used exclusively before the action is called.

In the OnActionExecuting call, if the model state is NOT valid, we need to return the 400 – Bad Request response as the result.

Now, let’s register this in our startup. We do this by applying it in the ConfigureServices call and specifically in the options of the AddMvc call:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(ValidatorActionFilter));
    });
}

And that’s it! So now your endpoints will return the proper response such as:

MyInputModel.cs

public class MyInputModel
{
    [Required]
    public string SomeRequiredValue { get; set; }
    public string SomeNotRequiredValue { get; set; }
}

MyController.cs

public class MyController : Controller
{
    public ActionResult DoSomeAction([FromBody]MyInputModel input)
    {
         return Ok("You did it"!)
    }
}

The request of:

{
    "someNotRequiredValue": "Hey"
}

Will return 400 - Bad Request - "The SomeRequiredValue field is required"

And the request of:

{
    "someRequiredValue": "Yo"
    "someNotRequiredValue": "Hey"
}

Will return 200 - Ok - "You did it!"

So go forth and validate those input models with ease!


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.