Category Archives: Programming

Targeting multiple frameworks in .NET

In this post we’re going to look at the process of targeting multiple .NET frameworks.

You may have seen this concept when installing nuget packages, viewing the package itself and noting that packages have lib folders which (in some cases) have multiple names such as net35, net40 etc. Hence having assemblies which are compatible with those versions of .NET.

For example, the packages/Castle.Core.4.2.1/lib folder contains

  • net35
  • net40
  • net45
  • netstandard1.3

The names are based upon, what’s called, the TargetFrameworkMoniker (or TFM for short), see Target frameworks in SDK-style projects for both a list of TFM’s as well as a Microsoft post of targeting multiple frameworks.

It looks like we need to be using the new SDK csproj files which we can create using either the dotnet CLI or by creating a .NET core or standard projects (or you can use conversion tools).

Let’s therefore walk through the steps for setting up a Class Library that can target a few different frameworks.

  • Create a .NET standard class library
  • Open the csproj file in Visual Studio or your preferred editor
  • Change the following
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
      </PropertyGroup>
    
    </Project>
    

    to use TargetFrameworks (plural) and add any frameworks you’re targeting delimited by a semi-colon, i.e.

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFrameworks>netstandard2.0;net45</TargetFrameworks>
      </PropertyGroup>
    
    </Project>
    
  • Save and if necessary reload Visual Studio to see the effects of these changes.

If all went well you should see The Dependencies section of your project (within Visual Studio) lists both

  • .NETFramework 4.5
  • .NETStandard 2.0

If you now build your project you’ll get both net45 and netstandard2.0 folders/builds in the bin/Debug and bin/Release folders.

We can now either explicitly add assemblies or packages to our framework specific dependencies and ofcourse, by using preprocessor symbols such as NETSTANDARD2_0 and NETFRAMEWORK or NET45 we can begin to conditionally compiler code for the different target frameworks.

We can add nuget to install package and add references to our multiple targets, but in some circumstances we might need to be more specific about which package is referenced by which target.

In such cases we can add the reference to the application using Visual Studio and then edit the csproj ourselves to add a Condition around the reference, for example

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
  <PackageReference Include="Microsoft.Net.Http" Version="2.2.29" />
</ItemGroup>

In this example, only the .NET 3.4 target will get the reference added to it.

Now we’ve seen how to add conditions to our csproj we can also define constants for use also (or ofcourse using the project properties tab within Visual Studio to add these), for example

<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
   <DefineConstants>SOME_CONSTANT</DefineConstants>
</PropertyGroup>

References

Target frameworks in SDK-style projects
Support multiple .NET versions
.NET Standard

Converting old style csproj to new style sdk

This tool’s pretty good for converting the old style csproj files to the new SDK style.

Just install using

dotnet tool install --global Project2015To2017.Migrate2019.Tool

Now navigate to where your solution is (that you want to convert) and from the command prompt run

dotnet migrate-2019 wizard "D:\Path\To\My\TestProject.sln"

You’ll be asked if you want to backup things and whether you want to migrate, answer Y to the migrate question (backing up is up to you). This will then locate all the csproj’s in the solution and convert them.

Tests are failing with DateTime expected format

I’m creating some builds on appveyor for some of my GitHub projects and hit a small snag. All of the DateTime’s in my tests have test data in the en-GB format, i.e. dd/MM/yyyy.

Note: Whilst I haven’t checked, I suspect appveyor is hosted on en-US machines.

A simple way to resolve this is, just add a NUnit SetUp that converts the current culture to the expected culture, i.e.

SetUp]
public void SetUp()
{
   var culture = new CultureInfo("en-GB");
   Thread.CurrentThread.CurrentCulture = culture;
   Thread.CurrentThread.CurrentUICulture = culture;
}

.NET Channels

This post is based upon a Channel9 video with Stephen Toub, I recommend you go and watch it (see references) if you’re interested in threadsafe producer/consumer mechanisms.

This is the namespace you want to be looking at

using System.Threading.Channels;

There are two types of channel, bounded and unbounded.

Bounded channels have a fixed size. In this example the queue within the channel will only allow a maximum of 10 items, meaning if we try to write more than the 10 items, the write method would block until an item is removed/read from the queue

var c = Channel.CreateBounded<int>(10);

So from this, we can tell that unbounded means the queue within the channel in unlimited in size. We create an unbounded channel like this

var c = Channel.CreateUnbounded<int>();

When we want to add items to the channel we use code such as the following, obviously if the queue has reached a limit (bounded) then this will block

c.Writer.TryWrite(123);

To read a value from the channel (if one exists) we use

await c.Reader.ReadAsync()

References

Working with Channels in .NET
An Introduction to System.Threading.Channels

Websockets with Fleck

I’m going to create a .NET core console application to demonstrate using Fleck.

So create yourself a project and add the Fleck nuget package or simply add the Fleck nuget package to an existing project.

Creating a websocket server

To begin with, we simply create a websocket server, supplying the “location”, i.e.

var websocketServer = new WebSocketServer("ws://0.0.0.0:8181");

Don’t forget the using Fleck; line at the start of your code

In this example we’re using 0.0.0.0 (the non-routable meta-address) along with the port 8181 and ofcourse we prefix this with the ws protocol.

Interacting with clients

Next up we’ll want to start the server and intercept various events/messages. Fleck uses a callback function/delegate style, so we simply supply our functions for each of the connection methods that we wish to intercept, for example

websocketServer.Start(connection =>
{
  connection.OnOpen = () => 
    Console.WriteLine("OnOpen");
  connection.OnClose = () => 
    Console.WriteLine("OnClose");
  connection.OnMessage = message => 
    Console.WriteLine($"OnMessage {message}");
  connection.OnBinary = bytes => 
    Console.WriteLine($"OnBinary {Encoding.UTF8.GetString(bytes)}");
  connection.OnError = exception => 
    Console.WriteLine($"OnError {exception.Message}");
  connection.OnPing = bytes => 
    Console.WriteLine("OnPing");
  connection.OnPong = bytes => 
    Console.WriteLine("OnPong");
});

Note: if we’re handling different state for different connections to the same url, it’s our responsibility to create our own form “session state”.

In this example, we’ve listed all the OnXXX actions that we can intercept.

Obviously OnOpen occurs when a new client connects to the server (on ws://0.0.0.0:8181) and OnClose occurs if the client closes the connection.

OnMessage is called when string messages are sent over the websocket, whereas OnBinary is, ofcourse, the binary equivalent (in the example above we’re assuming the bytes represent a string, obviously change this if you’re sending raw byte data).

OnError is called with an Exception for instances where exceptions occur (as you’ll have surmised).

OnPing is used when being pinged and like wise OnPong is used when receiving a pong – ping and pong are used as ways to, in essence, check if the client or server are still running. If supported, a server might send a ping to the connected clients then mark the clients as stopped (and hence dispose of any connections) if the server does not receive a pong within a specified timeout period. Obviously one of the biggest problems for any server that is maintaining some form of state is at what point they can assume the client is no longer around. Obviously if the client closes the connection the server can handle this, but what about if they just disconnect – this is where ping and pong come into play.

Obviously we also need to be able to send data to the client, hence we use the connection’s Send method. For example let’s change the OnMessage delegate to send an “Echo” of the message back to the client

connection.OnMessage = message =>
{
  Console.WriteLine($"OnMessage {message}");
  connection.Send($"Echo: {message}");
};

Writing a client to test our server

Let’s now create a simple console app to test our server code. This will use the System.Net.WebSockets ClientWebSocket class.

We will need to actually specify a network address for the client, so we’ll use the loopback 127.0.0.1.

Below are the contents of our client console application’s Main method

var websocketClient = new ClientWebSocket();
var cancellationToken = new CancellationTokenSource();

var connection = websocketClient.ConnectAsync(
  new Uri("ws://127.0.0.1:8181"), 
  cancellationToken.Token);

connection.ContinueWith(async tsk =>
{
  // sends a string/text message causes OnMessage to be called
  await websocketClient.SendAsync(
    new ArraySegment<byte>(Encoding.UTF8.GetBytes("Hello World")),
    WebSocketMessageType.Text,
    true,
    cancellationToken.Token);

  // receives a string/text from the server
  var buffer = new byte[128];
  await websocketClient.ReceiveAsync(
    new ArraySegment<byte>(buffer), cancellationToken.Token);
  Console.WriteLine(Encoding.UTF8.GetString(buffer));

  // sends a string/text message causes OnBinary to be called
  await websocketClient.SendAsync(
    new ArraySegment<byte>(Encoding.UTF8.GetBytes("Hello World")),
    WebSocketMessageType.Binary,
    true,
    cancellationToken.Token);
  });

  Console.WriteLine("Press <enter> to exit");
  Console.Read();

  // close the connection nicely
  websocketClient.CloseAsync(
     WebSocketCloseStatus.NormalClosure, 
     String.Empty, 
     cancellationToken.Token);

  // this will cause OnError on the server if not closed first
  cancellationToken.Cancel();

Hopefully it’s fairly self explanatory what’s going on – we create a websocket client and a cancellation token (as the methods all required one). We connect to the server and when a connection is established we send and receive data (strings and then binary). Eventually we close the connection.

What and ping and pong?

At this time I don’t have any examples to implement these.

In the case of the ClientWebSocket code, if you leave the client and server running you will periodically see OnPing being called.

I almost forgot…

We can also interact with the connection’s ConnectionInfo property which gives us access to headers, cookies and whether path was specified, i.e. the client url ws://127.0.0.1:8181/somepath will result in ConnectionInfo.Path having the value /somepath.

Here’s an example of the server changes for OnOpen

connection.OnOpen = () =>
{
  Console.WriteLine("OnOpen");
  Console.WriteLine(connection.ConnectionInfo.Path);
};

From what I can tell, each connection is assigned a GUID (found in ConnectionInfo.Id), so when handling multiple different clients with different state requirements we should be able to use this Id.

References

Fleck
Writing WebSocket servers

So _ are called discards

I’ve used the _ (underscore) previously in code – particularly with F# tuples but also C#. It is used to denote a value that is intentionally unused, ignored, discarded.

It seems that the underscore used in such situations has a name (maybe it has the same name in other languages, I’ve not yet checked). It’s called a discard.

Note: With regard to its use in C#, it appeared with C# 7.0.

Let’s have a look at a very simple example

public bool IsNumber => Double.TryParse("123", out _);

This slightly contrived example (the best I could think of quickly) shows how this might be used. In this example we’re not interested in the out value so just use a discard to basically say “this is unused, ignore it”.

Note: The discard doesn’t need a var or type.

Obviously the discard comes in very useful with tuples. I guess, for C#, this became most useful when tuples became a first class language feature.

So for example we might have this code

public (string, string, int) GetPerson()
{
   return ("Scooby", "Doo", 13);
}

// in use we only want the age
var (_, _, age) = GetPerson();

The “UNAVAILABLE: Trying to connect an http1.x server” gRPC error

I’m working with on C# client library using gRpc. This is not a web based library where there’s a need for envoy or other application to help work with HTTP2. Instead this was on a C# client using tcp/ip.

Everything was working fine on my machine until the machine was relocated (not that this specifically was the problem as I later found out others were having similar problems, some times intermittently) at which point I found that the client would exception with the message “UNAVAILABLE: Trying to connect an http1.x server”.

Note: if you turn on all exceptions within Visual Studio, you’ll firstly see an exception where grpc tries to get a Value from a Nullable when it’s null (this was the call to Native.grpcsharp_batch_context_recv_message_length). This is a red herring, it’s simple that the nullable is null which seems to be expected behaviour, maybe should be handled in the gRPC .NET library code.

Testing the client on another machine demonstrated the problem was seemingly network related, turns out it was HTTP proxy related to be precise.

This doesn’t seem to be too well documented from what I could tell, but setting the ChannelOption grpc.enable_http_proxy to 0 (see https://grpc.github.io/grpc/core/group__grpc__arg__keys.html) fixed the problem.

var channel = new ManagedChannel(
   host, 
   port, 
   ChannelCredentials.Insecure,
   new []{ new ChannelOption("grpc.enable_http_proxy", 0)} );

Razor templates in your Xamarin application

I had a situation where I wanted to have a template file made up of HTML along with data supplied by my Xamarin application. There are several options to do this but a Razor template file would be a perfect fit, but how to embed one in my (non-Web) application?

Note: Whilst this post talks about a Xamarin application this should be usable in other types of application.

  • I created a Templates folder (not required for this to work) in my solution.
  • Within the Templates folder I add a new text file but saved with a .cshtml extension, for example EmployeeTemplate.cshtml. Visual Studio 2019 doesn’t have a specific template for Xamarin application, but just naming it with the correct extension works.
  • Select the file in the solution explorer and open it’s properties, set the Custom Tool to RazorTemplatePreprocessor.

Here’s a snippet of the contents within the Razor template file

<div class="row">
  <div>Date: @Model.DateEntered</div>
    <div>
      <div>Employee Number:</div>
      <div>@Model.OrderDetails.EmployeeNumber</div>
    </div>
</div>

Visual Studio will (due the use of the RazorTemplatePreprocessor Custom Tool) generate a .cs file that is a class that we can pass our model into and will process the template file and output a string representing the combination of the template with our model.

To generate our output string we simply use the following code

var template = new EmployeeTemplate() 
{ 
  Model = viewModel 
};

var result = template.GenerateString();

Text to Speech on mobile with Xamarin

Previously I looked at Speech synthesis in Windows with C# but what about speech synthesis on mobile.

Xamarin.Essentials has this covered with the TextToSpeechTextToSpeech class and is included by default when creating a Xamarin Forms mobile application.

It’s really simple to add text to speech capabilities, we simply write code such as

await TextToSpeech.SpeakAsync("Hello World");

As you can see by the use of the await keyword (and the standard Async suffix), the SpeakAsync method returns a task. It also accepts a cancellation token if you need to cancel mid utterance. There’s also an overload which accepts SpeechOptions which allows us to set the volume, pitch and locale.

The second TextToSpeech method is GetLocalesAsync which allows is to get a list of supported locales from the device that can then be used within the SpeakAsync method’s SpeechOptions.

await TextToSpeech.GetLocalesAsync();

Note: It’s fun listening to the attempts at different accents depending upon the locale.

Requesting permissions in Android with a Target SDK Version >= 23

Various Android permissions (classed as “dangerous”), within applications targeting Android SDK >= 23 now require “requesting”.

So for example, on older Android versions we simply set the permissions, such as those for accessing Bluetooth, within the AndroidManifest.xml (or via the editor within Visual Studio – I’m using Xamarin Forms for my application, hence Visual Studio). These look like this

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

All works fine until you try to run your application (which requires these permissions) on an Android device with a >= 23 version. Instead, within the debug output you’ll see Security Exceptions around such permissions.

So along with our manifest, we now need to request these permissions within the MainActivity.cs we can write something like

private void CheckPermissions()
{
   ActivityCompat.RequestPermissions(this, new []
   {
      Manifest.Permission.AccessCoarseLocation,
      Manifest.Permission.AccessFineLocation,
      Manifest.Permission.Bluetooth,
      Manifest.Permission.BluetoothAdmin
   }, 1);
}

We might wish to first check whether a permission has already been granted, using code such as

if (ContextCompat.CheckSelfPermission(
   this, Manifest.Permission.AccessCoarseLocation) 
   != Permission.Granted)
{
   // request permission
}

On top of this, we probably want to either inform the user or handle failures to get the requested permissions (for example disabling such functionality), in such cases we override the OnRequestPermissionsResult method within the MainActivity.cs file (i.e. within the FormsAppCompatActivity class)

public override void OnRequestPermissionsResult(
   int requestCode, 
   string[] permissions, 
   Permission[] grantResults)
{
   // we may want to handle failure to get the permissions we require
   // we should handle here, otherwise call the base method
   base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

See Permissions In Xamarin.Android, also see the Android documentation Permissions Overview.