Monthly Archives: September 2017

Beware those async void exceptions in unit tests

This is a cautionary tale…

I’ve been moving my builds to a new server box and in doing so started to notice some problems. These problems didn’t exist on the previous build box and this might be down to the updates versions of the tools, such as nant etc. I was using on the new box.

Anyway the crux of the problem was I was getting exceptions when the tests were run, nothing told me what assembly or what test, I just ended up with

NullReference exceptions and a stack trace stating this

System.Runtime.CompilerServices.AsyncMethodBuilderCore.b__0(System.Object)

Straight away it looks like async/await issues.

To cut a long story short.

I removed all the Test assemblies, then one by one place them back into the build, running the “test” target in nant each time until I found the assembly with the problems. Running the tests this way also seemed to report more specifics about the area of the exception.

As we know, we need to be particularly careful handling exceptions that occur within an async void method (mine exist because they’re event handlers which are raised upon property changes in a view model).

Interestingly when I ran the Resharper Test Runner all my tests passed, but switching to running in the tests in Debug showed up all the exceptions (ofcourse assuming that you have the relevant “Exceptions” enabled within Visual Studio). The downside of this approach, ofcourse, is that I also see all the exceptions that are intentionally tested for, i.e. ensuring my code exceptions when it should. But it was worth it to solve these problems.

Luckily none of these exceptions would have been a problem in normal running of my application, they were generally down to missing mocking code or the likes, but it did go to show I could be smug in believing my tests caught every issue.

net share is my friend

I recently had to set-up some shares on a server box using File Explorer and the share menu option, but after a reboot they all disappeared.

Note: I’m not concerned by this behaviour, of losing the shares, as it’s probably down to some security policy but every now and then it’s so much easier having the shares available to work from when I need to deploy apps etc.

Anyway, using net share in a batch file saves the day.

Just run

net share

to view the current shares on your machine.

Now to create a share, simply use

net share DEPLOYMENT=d:\mydeployment /GRANT:EVERYONE, READ

In this case I’m actually creating a READ only share with access granted to everyone. The string to the left of the = operator is the sharename (i.e. what you’ll see or use to access the share) obviously the right hand side is the location on the machine the share points to.

Obviously EVERYONE might by less than great in terms of security, so instead you can GRANT individual user’s access. The permission can be READ | CHANGE | FULL, see the output of net share /?

The syntax of this command is:

NET SHARE
sharename
          sharename=drive:path [/GRANT:user,[READ | CHANGE | FULL]]
                               [/USERS:number | /UNLIMITED]
                               [/REMARK:"text"]
                               [/CACHE:Manual | Documents| Programs | BranchCache | None]
          sharename [/USERS:number | /UNLIMITED]
                    [/REMARK:"text"]
                    [/CACHE:Manual | Documents | Programs | BranchCache | None]
          {sharename | devicename | drive:path} /DELETE
          sharename \\computername /DELETE

Trying out Refit (a REST client library)

REST is cool in that it’s lightweight and simple to use but lacks a lot of the tooling etc. that SOAP/XML has.

In .NET we have libraries such as ServiceStack (and others) to enable generation of REST services to be fairly painless, there are also a few client frameworks out there, but for this post I’m looking at Refit which (as the documentation states) is automatically type-safe and available in .NET standard 1.4 which also includes Xamarin, UWP and desktop. So pretty universal in it’s availability.

Show me the code!

Enough chat, let’s get into the code. I’m going to use ServiceStack to generate a simply REST service, the default one is the “Hello” service, which in code looks like this

[Route("/hello/{Name}")]
public class Hello : IReturn<HelloResponse>
{
   public string Name { get; set; }
}

public class HelloResponse
{
   public string Result { get; set; }
}

and this will be called using http://127.0.0.1:8088/hello/World which in turn returns (in JSON format)

{"Result":"Hello, World!"}

All pretty simple.

One thing we will do, is switch ServiceStack to use JSON be default, so in the MyService generated code we’ll add an AddHeader attribute, so it will look like this

public class MyServices : Service
{
   [AddHeader(ContentType = MimeTypes.Json)]
   public object Any(Hello request)
   {
      return new HelloResponse { Result = "Hello, {0}!".Fmt(request.Name) };
   }
}

Creating our client

Fire up Visual Studio and create a console application (I’ve targeted .NET 4.6), then add Refit via NuGet.

As we already have the HelloResponse class from our ServiceStack sample application, we can just copy that into our Refit application, or visit https://quicktype.io/ and paste {“Result”:”Hello, World!”} into the JSON edit box on the left of the site and it’ll create the class for us. So using either method we need to add the JsonProperty so it now looks like this in our Refit app.

public class HelloResponse
{
   [JsonProperty("Result")]
   public string Result { get; set; }
}

Next up we need create an interface that calls our REST service. We know, having written/generated the code for the service that there’s a Hello class that defines the route and response, but we won’t be copying this, instead Refit likes to use methods returning a Task (which makes sense being a web service call) so create (in your Refit app.) the following

public interface IHelloService
{
   [Get("/hello/{name}")]
   Task<HelloResponse> SayHello(string name);
}

Note we create an interface and that the route is within the Get attribute points to our Hello endpoint. Next we created a method to be called to contact our endpoint at the aforementioned route. This is the main area where we actually have to do any coding for this example to work.

Let’s now create the client code

var svc = RestService.For<IHelloService>("http://127.0.0.1:8088");
var response = svc.SayHello("World");

and that’s it – obviously you’ll need to await or Result etc. to get the actually HelloResponse object, but that’s all there is to this (admittedly very simple example).

As you can see the RestService.For method creates an instance of an IHelloService for us acting as a transparent proxy through to the service.

References

The automatic type-safe REST library for Xamarin and .NET
Exploring refit, an automatic type-safe REST library for .NET Standard

Writing your first Azure Function

With serverless all the rage at the moment and AWS Lambda’s and Azure Functions offering us easy routes into serverless in the cloud, I thought it about time I actually looked at what I need to do to create a simple Azure function.

Creating a function using the portal

  • Log into https://portal.azure.com/
  • From the Dashboard select New
  • Select Function App
  • Supply an App name, set your subscription, location etc. then press Create (I pinned mine the dashboard also using the Pin to dashboard checkbox)
  • After a while (it’s not instant) you’ll be met with options for your Function Apps, Functions, Proxies and Slots.
  • Click in the + of functions
  • Select HttpTrigger – C# or whatever your preferred language is, other triggers can be investigated later but this basically creates a simple REST like function, perfect for quick testing
  • Give your function a name and for now leave the Authorization level alone

I used the default name etc and got the following code generated for me by Azure’s wizard.

Note: Whilst there is some information out there on renaming Azure functions, the current portal doesn’t seem to support this, so best to get your name right first time or be prepared to copy and paste code for now into a new function.

using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    // parse query parameter
    string name = req.GetQueryNameValuePairs()
        .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
        .Value;

    // Get request body
    dynamic data = await req.Content.ReadAsAsync<object>();

    // Set name to query string or body data
    name = name ?? data?.name;

    return name == null
        ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
        : req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
}

This is basically the Hello World of Azure functions. If you run it from the portal you’ll see the output “Hello Azure” as well as logs output. The request box allows you to edit the “name” field which is sent to the function.

By default the authorization level is Function, which basically means that a key is required to run this function. If you click the </> Get function URL link, Azure will supply the fully URL, minus the request payload and this will include the text code=abc123 where abc123 represents a much longer key.

Note: you can find your keys also via the Manage option below the Functions list on the left of the portal. Click the “Click to show” on Function Keys default.

We can remove the requirement for the key and make the function accessible to anonymous users by selecting the Integrate option under the Function name on the left list of the portal and changing Authorization level to Anonymous.

Beware that you’ll be allowing anyone to call your function with the Anonymous option which ultimately ends with your account paying for usage.

Now, once you have the URL for you function just append &name=World to it and navigate to the function via your browser (remove the code= text and don’t bother with the & for anonymous access).

Creating and deploying from Visual Studio 2017

If you have the Azure tools installed then you can create Azure functions directly in Visual Studio (I’m using 2017 for this example).

  • File | New Project
  • Select Cloud | Azure Functions (or search for it via the search box)
  • Name your project, mine’s HelloWorldFunctions
  • At this point I build the project to bring in the NuGet packages required – you can obviously do this later
  • Add a new item to the project, select Azure Function, mine’s named Echo.cs
  • Select HttpTrigger to create a REST like function
  • Leave Access rights to Function unless you want Anonymous access

When completed, we again get the default Hello Azure/World sample code. We’re not going to bother changing this at this time, but instead will look to deploy to Azure. But first, let’s test this function in Visual Studio (offline). Simply click the run button and a console window will open with a web server running mimicking Azure, mine creates makes the function available via

http://localhost:7071/api/Echo

If we run this from a web browser and add the ?name=, like this

http://localhost:7071/api/Echo?name=Mark

we’ll get “Hello Mark” returned.

Okay, so it’s working fine, let’s deploy/publish it.

  • Right mouse click on the project
  • Select Publish…
  • Either create new or select existing (if you already have an app), you may need to enter your account details at this point
  • In my case I created the application via the Portal first so I selected existing and then select my application from the options available
  • Press OK
  • Eventually the Publish button will enable, then press this

This will actually publish/deploy the DLL with your Azure function(s) to the Azure application. When you view the function in the Azure Portal you won’t see any source code as you’ve actually just deployed the compiled DLL instead.

In the portal, add your Request body, i.e.

{
   "name" : "Azure"
}

and run from the Portal – this is basically a replica (at the functional level) of the portal’s created default function.

Let’s look at the code

I’m going to show the code created via the Visual Studio template here

public static class Echo
{
   [FunctionName("Echo")]
   public static async Task<HttpResponseMessage> Run(
      [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
      HttpRequestMessage req, TraceWriter log)
   {
      log.Info("C# HTTP trigger function processed a request.");

      // parse query parameter
      string name = req.GetQueryNameValuePairs()
         .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
         .Value;

      // Get request body
      dynamic data = await req.Content.ReadAsAsync<object>();

      // Set name to query string or body data
      name = name ?? data?.name;

      return name == null ? 
        req.CreateResponse(HttpStatusCode.BadRequest, 
           "Please pass a name on the query string or in the request body")
       : req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
   }
}

If you’ve used any C# or Java HTTP like functions, this will all seem pretty familiar.

Our function is passed two parameters, the first being the HTTP request message and the second is the logging object. Obviously the logger is pretty self explanatory.

The HttpRequestMessage contains all those sorts of things we’d expect for an HTTP request, i.e. query name parameters, headers, content etc. and like many similar types of functions we return an HTTP response along with a result code.