Tuesday, 3 May 2016

Swagger based Web API with C# (1/2) : Swashbuckle

This is the first of two blog posts on using Swagger with C#, and gives a step-by-step quick-start for creating a trivial web-API using Swashbuckle open-source package, to get something up and running.

A follow-up blog entry covers client code-generation for a C# client platform.


What's Swagger?

Web-APIs are trending at the moment and everyone wants one.

Swagger is the defacto leading industry standard - at least, for the time being - and is a well-supported markup language for specifying web-APIs.

There are plentiful toolsets out there for generating Swagger markup from web-API code, and generating client code from Swagger markup.


What's Swashbuckle?

Swashbuckle is an open-source toolset for generating Swagger markup from your C# web-API.  You get a documentation portal and test-harness for free, both of which can be accessed by your API users (and their integration tools).


Quick Start Guide


Step 1 - Create a Web API project.

  • Create a new VS2015 project.
  • It should be an ASP.NET Web Application.
  • Choose Empty Project but tick Add folders and core references for Web API.

  • Add a class, SampleController and derive it from ApiController.
  • Add a Get method like the one below.


  • View the Web properties for your project.
  • Paste the Project URL into the Start URL field.
  • Then add api/ followed by your controller name.

  • Run the application and see that the controller Get method works.


Step 2 - Add Swashbuckle

  • Add the Swashbuckle package from Nuget in Visual Studio.

  • Edit the Swagger.Config file created by Nuget in App_Start.
  • Modify the configuration to read as below.
  • Note that we filled in a path for the XML comments file.
 

  • Set the project build properties to create the XML comments file.

  • View the Web properties for your project.
  • Set the Start URL now to be the documentation URL.
 

  • Add a route attribute to your method.
  • Also add some XML method documentation.

  • Run up your project and view the API documentation portal.
  • Click on the text Sample to see the Get method.
  • Note that our XML comment propagated to the portal.

  • Click on the Get method to see its definition.
  • If the method took arguments, they would be displayed here.
  • Click on the Try it out! button to make a call to the API.


Next?

Now you have a basic web-API setup: now you can make the return type more complex, add parameters, add more methods, add more controllers...

Remember to comment the parameters, methods and controllers for a rich, self-documenting API.

There are plenty of code-generators for generating clients in various languages from a Swagger specification.  If you want to create one in C# you could skim my next post, on NSwag.

Friday, 25 September 2015

How to set up Mono in Amazon Web Services

We want to run Mono in an AWS EC2 Linux instance but the default yum package for Mono is really out of date: soooo out of date that it won't even compile the latest source code (remember that to compile Mono source you need an already functioning, recent version of Mono)!

So we're going to have to build from scratch. Before we start, you will need to:
This article was pulled together from multiple sources - but Brad's post was particularly useful.


Setting up the Prerequisites


We want the latest version of all build components, plus the Extra Packages For Enterprise Linux for which yum is already configured but which is disabled by default.  So, edit the repository definition to enable the first EPEL entry (which is the run-time) by entering the following commands:
cd /etc/yum.repos.d
sed '0,/^enabled=0/s/enabled=1/' <epel.repo >/tmp/epel.repo
sudo cp /tmp/epel.repo .
Now we can update all repositories to their latest versions:
sudo yum update
And get some build tools that aren't installed by default:
sudo yum install autoconf libtool gettext make automake gcc gcc-c++


Getting the Sources


Install git so that we can download the sources (the git install at time of writing is about 10MB):
sudo yum install git
Make somewhere to download the Mono sources and download them (be cognisant of the size):
mkdir src
cd src
git clone https://github.com/mono/mono


Compiling the Sources


Build the Mono bootstrapper:
cd mono
./autogen.sh --prefix=/usr/local
make get-monolite-latest
Use the bootstrapper to build Mono, then install it:
make EXTERNAL_MCS="${PWD}/mcs/class/lib/monolite/basic.exe"
sudo make install
But that's not enough.  If you were to return to the source tree and make check you would find that one or two of the tests fail - in particular, one around unhandled exceptions in mscorlib.  We can't accept that but at least the newly installed Mono is better than the monolite version.  So let's clean up and compile again: this time with our newly built version as the compiler.
make clean
./autogen.sh --prefix=/usr/local
make
sudo make install
You should make check now if you have time, just to prove that the new version is clean.
If you wish to try out your new toy, copy the text below into a file called HelloWorld.cs:
public class HelloWorld {
    public static void Main() {
        System.Console.WriteLine("Hello World");
    }
}
Then compile and execute, by:
mcs HelloWorld.c
mono HelloWorld.exe

Monday, 21 September 2015

Connecting to an AWS Linux Instance

Connecting to a Linux EC2 Instance over SSH


So you've created a Linux EC2 instance in Amazon Web Services, with a key-pair, and now you need to connect to it over SSH.  For this we'll need:
  • A copy of the PuTTY and PuTTYgen programs, downloaded from the internet.
  • Your key file that was generated when you created the instance.
  • Your instance's IP address, which you can get from the Amazon EC2 page.

Downloading PuTTY and PuTTYgen

PuTTY is a free Telnet and SSH client which we will use to connect to our Linux instance.
PuTTYgen is a tool which will convert our key-file into a form suitable for PuTTY.
The tools are in beta, but they have been for years, like Google products.  They're stable.

Download PuTTY and PuTTYgen from the PuTTY download page by clicking each EXE.
Save them to your local hard-drive wherever is easily accessible: no installation required!



Converting your .PEM key-file to .PPK

To connect to your instance using PuTTY you need a private key file (ending in .ppk).
We'll use PuTTYgen to convert our Amazon key-file (ending in .pem) to that format.
Click the PuTTYgen binary to start the conversion program:


Ensure that SSH-2-RSA is selected as the type, then click Load.
Pick the .pem key-file from Amazon (choose All Files in the file-type drop-down).
Then click Open to load the key:


Once the key is loaded, it can be saved in .ppk format.
You can add a passphrase if you are happy to type that every time you connect.
Then create the private key file in a memorable location by clicking Save private key.


Now close the PuTTYgen application.


Connecting using PuTTY

Open the PuTTY application by clicking it.
In the Host Name box enter ec2-user@ followed by the IP address for your AWS instance.

Then expand the SSH node (under Connection in the left hand side-bar) and expand Auth.
Click Browse and select the private key (.ppk) file that you saved earlier.
Then click Open to connect to your Amazon instance.


And we're done.

Creating an AWS Linux Instance

Creating an Amazon EC2 Linux Micro Instance

We're going to create a Elastic Compute (EC2) micro instance in AWS running Amazon's own cut of Linux.  It's free-tier eligible but if you aim to try to stay free, remember to set up alarms and alerts to keep you informed of your usage and optionally shut down the instance if you hit the free-tier limit.

Log on to AWS and click the EC2 link (main pane, top left, under Compute):


Choose your closest region (menu-bar, top right) and click Launch Instance:


Tick the Free Tier Only checkbox (left side-bar) and choose your image.
Choose Amazon Linux AMI, in my case it's top of the list.  Click Select to the right of it:


Select a free tier Amazon Linux instance (in my case the t2.micro at the top of the list).
Then click Review and Launch:


This generates a mostly complete configuration.  Check it over to be sure.
If your desktop machine has a fixed IP address (or range), edit your security group.
Edit the tags to give your instance a name (add a tag called Name and set its value).
Then click Launch.


Select to Create A New Key Pair from the drop-down and enter a memorable name.
Then click Download Key Pair and save it to a safe location which you'll remember.
If you lose the downloaded file you won't be able to login to your instance so keep it safe!
Now click Launch Instances to finally start-up your new virtual machine!


It will take about 5 minutes to launch your instance: go make a cup of your beverage of choice.
And we're done!  Now we need to connect to it!

Next up: Connecting to an AWS Linux Instance

Sunday, 8 March 2015

Free Speech

I've always wanted to do some basic speech analysis using comforting, old C#.
The pretext is simple, but any implementation would certainly be non-trivial:
  • Take some spoken sentences.
  • Break down each sentence into its words.
  • Analyse the words for their component phonemes.
  • Build a library of these by analysing multiple sound samples.
  • Tease out the commonality and factor out accent and expression.
  • Construct a mechanism for recombining the sounds and applying expression.
  • Voila! Speech synthesis (like no-one's done that, already - ah! the arrogance!).
If I can get as far as extracting and analysing the phonemes, I'll have learned something!

Firstly, I'll need some voice samples:
  • EUSTACE is an academic site with some royalty free downloads - they'll do.
  • The voices are mostly expressionless and the quality is pretty good.
  • They're available as either ESPS files (meh!) or RIFF (.wav) files.
  • ESPS is awkward so let's go with the WAVE files.
On to the parsing of the files:
  • This article on the Microsoft site on the WAVE format has typos on field sizes.
  • This one is much better: concise, clear and seems free of fundamental errors.
  • The parsing is trivial: either write a simple class or wrap the Win32 utilities.
I'll also need a free Fast Fourier Transform implementation for the frequency-analysis:
  • I've used ExoCortex before: that was for .NET 2 and could do with refactoring.
  • Better seems to be Lomont FFT which is more up-to-date (2010) and compact.
  • It's kind of Chris to have coded and shared it, and the quality seems good.
  • Briefly searching t'internet yields no bug-whines.
  • Just a few control-comments to help ReSharper swallow it without hiccoughs.
All set up! Now for some exploratory coding.

Tuesday, 2 December 2014

Use of "await" with WCF-lifetime dependency injection (SimpleInjector)

Found an issue where SimpleInjector WCF-lifetime dependency-injection is broken by asynchronous methods.  The code in question is as follows.  (The deferred construction is performed because the legacy repository is not required by any of the other methods on the class)

        public async Task<UnitQueryResult[]> GetUnitsByVinAsync(string vin)
        {
            return await ExecuteFaultHandledOperation(async () => {
                var result = (await _factory
                    .Build<ISalesForceRepository>()
                    .GetUnitWithReferencesByVin(vin)) ?? new UnitQueryResult[0];

                if (_settings.IsLegacyUnitLookupEnabledForSalesForce)
                {
                    result = result.Concat(
                        (await _factory.Build<ISvrLegacyRepository>()
                            .GetUnitWithReferencesByVin(vin)) ??
                                new UnitQueryResult[0]).ToArray();
                }
                return result;
            });
        }

The exception raised by the yellow code when called from a WCF method is:

The registered delegate for type ISvrLegacyRepository threw an exception.
The ISvrLegacyRepository is registered as 'WCF Operation' lifestyle, but
the instance is requested outside the context of a WCF Operation.

The reason is clear but worrying … by the time the method on the legacy repository is called, the original thread (with its context) has been lost due to the prior await a method on the other repository … so a workaround would be to instantiate the legacy repository before the first await – for example:

        public async Task<UnitQueryResult[]> GetUnitsByVinAsync(string vin)
        {
            return await ExecuteFaultHandledOperation(async () => {
                var legacyRepository = _settings.IsLegacyUnitLookupEnabledForSalesForce?
                    _factory.Build<ISvrLegacyRepository>():
                    null;

                var result = (await _factory
                    .Build<ISalesForceRepository>()
                    .GetUnitWithReferencesByVin(vin)) ?? new UnitQueryResult[0];

                if (legacyRepository != null)
                {
                    result = result.Concat(
                        (await legacyRepository.GetUnitWithReferencesByVin(vin)) ??
                        new UnitQueryResult[0]).ToArray();
                }
                return result;
            });
        }

However, that makes for fragile code, because it depends on the whole call-chain before the use of the factory: if any method in the call-stack prior to a use of the factory to instantiate a WCF-lifetime object has already performed an await, the WCF context is unavailable (we’re now running on a different thread, even though the WCF context is still alive) and instantiation via the factory will fail.  And that obviously won’t be picked up at unit-test L

So, another clear reason to strongly prefer all dependencies to be resolved by the constructor wherever possible.

Sunday, 3 March 2013

TypeScript with Visual Studio 2010 (VS2010) on Windows XP

I've been watching TypeScript for a while and would desperately love to use it, but whilst my home machine is Windows 7 with VS2012, my client-supplied work laptop is Windows XP with VS2010 (for reasons related to supporting legacy software).

TypeScript is open-source so there's no reason that I shouldn't be able to integrate it with VS2010 but Microsoft wish to compel their users to move to VS2012 so don't support VS2010 with their installer for it.

The Obvious Hacks Don't Work ...

The first thing I tried was to run the MSI for VS2012 on XP anyway - that didn't work because the MSI required a version of the installer not present on XP - dead end there as I can't upgrade the installer on my client's laptop even if a later version for XP is available.

The next avenue was to unpack the files in the MSI using 7zip ... in there I find the VSIX and the other installable components: the VSIX installed fine into VS2010 but didn't work well when it came to adding in .ts files even if I installed the TypeScript compiler manually. Worse, though: the license explicitly says that we're not permitted to work around technical limitations of the software - and using unlicenced software would not go down well with my client.

... So Let's Do It Cleanly (and Legally).

First install the TypeScript compiler standalone:
  • Go to NodeJS and click Install, following the very brief process to install it.
  • Open a normal command-prompt in XP and run:  npm install -g typescript 
A quick test verified that the compiler (tsc) runs up fine on Windows XP.
Now to integrate with VS2010 so that saving a .ts file automatically compiles it to a dependent .js file.
  • Ensure the VS2010 SP1 SDK is installed on VS2010.
  • Take a look at the Microsoft Single-File-Generator sample & docs.
  • Create an Extensibility project to generate a Visual Studio package.
  • Add a class which implements
    Microsoft.VisualStudio.Shell.Interop.IVsSingleFileGenerator.
  • Make the DefaultExtension method return .js.
  • Make the Generate method call out to tsc.cmd to get the compiled content.
  • Add attributes to make the class show as a custom tool.
  • Add registry entry to ensure .ts is associated with the custom tool.
That's pretty straightforward and I had it working quickly.  Current limitations:

  • Performance: it takes 2-3 seconds to save a file.
  • Productivity: no intellisense yet - need to research how to add that in.
  • Packaging: currently an extension with manual install - must create a VSIX.
  • Presentation: the icon for the .ts file type is currently the vanilla file icon.
And I suspect it probably works in VS2008 too - though I no-longer have a copy :)

There's probably a better way, but at least I have something ... will upload the project here when I've sorted out the intellisense and packaging - and maybe the performance as I believe I should be able to get it down to 1 second.