Wednesday, November 25, 2015

.NET WebSocket Libraries

WebSockets are awesome, and you should be using them. If you are working with .NET, then there are some very easy to consume libraries to help you host a WebSocket server or connect as a WebSocket client.

Below is a complete chat server and client made using ONLY these two libraries.

Saturday, October 31, 2015

How to change HttpClientHandler.AllowAutoRedirect

In the past I have talked about how the HttpClient is thread safe. This allows you to reuse the same HttpClient and be very efficient regarding how many ephemeral ports your application consumes.

Because the HttpClient and the HttpClientHandler both need to be thread safe, their properties become immutable after a request has been issued. If you are in a scenario where you need to change settings, such as whether or not the handler allows redirects, you will have to develop a little hack to work around the default behavior.

Below is a method where you can use reflection to set a private field and avoid the property setter from checking whether or not a request has been issued. This could cause thread safety issues, however with the current implementation of HttpCliehtHandler it is perfectly safe so long as only one thread is consume the client at a time.

HttpClientHandler Extension

public static class HttpClientHandlerExtensions
{
    private static readonly FieldInfo AllowAutoRedirectFieldInfo =
        typeof (HttpClientHandler).GetField(
            "allowAutoRedirect",
            BindingFlags.Instance | BindingFlags.NonPublic);
 
    public static void SetAllowAutoRedirect(this HttpClientHandler handler, bool value)
    {
        AllowAutoRedirectFieldInfo.SetValue(handler, value);
    }
}

Unit Test

public class HttpClientHandlerExtensionsTests
{
    [Fact]
    public async Task SetAllowAutoRedirectTest()
    {
        using (var handler = new HttpClientHandler())
        using (var client = new HttpClient(handler))
        {
            handler.AllowAutoRedirect = true;
 
            using (var response = await client.GetAsync("http://www.google.com"))
                response.EnsureSuccessStatusCode();
 
            Assert.Throws<InvalidOperationException>(() =>
            {
                handler.AllowAutoRedirect = false;
            });
 
            handler.SetAllowAutoRedirect(false);
        }
    }
}

Enjoy,
Tom

Sunday, October 25, 2015

Override Configuration via Command Line

In my previous blog posts I have talked about creating complex config objects from your app.config file, as well as how to have cascading configuration settings from multiple files. Now I want to build on that concept by taking in configuration from command line in a generic fashion that will override your other cascading settings.

Configuration Object

public class TestConfig
{
    public string Hello { get; set; }
    public string Goodnight { get; set; }
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="TestConfig.Hello" value="World" />
    <add key="TestConfig.Goodnight" value="Moon" />
  </appSettings>
</configuration>

Sunday, October 4, 2015

Throttles - Delay vs Semaphore

A while back I had talked about how to await an interval with a simple Throttle class that I had made. This is a very easy way to control how often you start an operation, but it does not ensure a limit to how many operations are happening at a given time.

Problem: You want to only make 5 requests per second to a remote service.

With the throttle class set to only allow one new call to start every 200 milliseconds you will only be able to start 5 new requests per second. However, if those calls take longer than two seconds to complete, then during the next second you will have 10 requests in flight at the same time.

Solution: Set your throttle to 200 millisecond and add a semaphore with a count of 5.

You can solve this problem by combining your throttle with a semaphore. This will ensure that you only start a new operation at your schedule frequency, and also that you never have more than a predetermined number in flight at the same time.

Please note that only using a semaphore would not solve the problem because if, in the same example, the calls take sub 200 milliseconds to complete then more than 5 requests will start each second.

Below is a set of helper classes (and tests) to help extend the throttle class to support this functionality within a using block.

Interfaces

public interface IUsableSemaphore : IDisposable
{
    Task<IUsableSemaphoreWrapper> WaitAsync();
}
 
public interface IUsableSemaphoreWrapper : IDisposable
{
    TimeSpan Elapsed { get; }
}
 
public interface IThrottle
{
    Task WaitAsync();
}

Wednesday, September 30, 2015

XDT Console Application

XML Document Transformations, or XTD, is a great way to transform your app and web config files between environments or builds. It is directly supported by Visual Studio and other third party tools, such as Octopus Deploy.

So how can you transform config files on your own? For starters uou can use great free tools like the Web.config Transformation Tester (which is open source) from AppHarbor.

Would you rather transform your files via command line? Then just do it yourself! Pull down the Microsoft.Web.Xdt package from NuGet, and then copy and paste this code to implement your own simple console app...

Program.cs

namespace XDT
{
  using System;
  using System.IO;
  using System.Text;
  using System.Xml;
 
  using Microsoft.Web.XmlTransform;
 
  public class Program
  {
    private static int Main(string[] args)
    {
      if (args.Length != 3)
      {
        Console.WriteLine("Required Arguments: [ConfigPath] [TransformPath] [TargetPath]");
        return 400;
      }
 
      var configPath = args[0];
      if (!File.Exists(configPath))
      {
        Console.WriteLine("Config not found");
        return 404;
      }
 
      var transformPath = args[1];
      if (!File.Exists(transformPath))
      {
        Console.WriteLine("Transform not found");
        return 404;
      }
 
      try
      {
        var targetPath = args[2];
        var configXml = File.ReadAllText(configPath);
        var transformXml = File.ReadAllText(transformPath);
 
        using (var document = new XmlTransformableDocument())
        {
          document.PreserveWhitespace = true;
          document.LoadXml(configXml);
 
          using (var transform = new XmlTransformation(transformXml, false, null))
          {
            if (transform.Apply(document))
            {
              var stringBuilder = new StringBuilder();
              var xmlWriterSettings = new XmlWriterSettings
              {
                Indent = true,
                IndentChars = "  "
              };
 
              using (var xmlTextWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings))
              {
                document.WriteTo(xmlTextWriter);
              }
 
              var resultXml = stringBuilder.ToString();
              File.WriteAllText(targetPath, resultXml);
              return 0;
            }
 
            Console.WriteLine("Transformation failed for unknown reason");
          }
        }
      }
      catch (XmlTransformationException xmlTransformationException)
      {
        Console.WriteLine(xmlTransformationException.Message);
      }
      catch (XmlException xmlException)
      {
        Console.WriteLine(xmlException.Message);
      }
 
      return 500;
    }
  }
}

Enjoy,
Tom

Saturday, September 26, 2015

How to only Serialize Interface Properties with Json.NET

When you serialize an object with Newtonsoft's Json.NET it will resolve the serialization contract for the type being serialized. This means that if you want to serialize an object so that it matches one of the interfaces that it implements you will need to use a customized contract resolver.

When I first tried to do this I made a completely custom JsonConverter for the type that looked up the properties via reflection and just wrote their values out manually. Unfortunately had the side effect of bypassing all of the features the Newtonsoft provides with regard to decorating classes and customizing the serialization process for that object.

There was a good topic on Stack Overflow about this that led me to the custom contract resolver solution. However the sample implementation there is hard coded to only try to serialize one hard coded type for all serialization.

Below is an implementation (with tests) that allows you to specify a list of interfaces that you want to serialize by, and then if the object being serialized does implement that interface it will fall back on it's default contract.

InterfaceContractResolver Implementation

public class InterfaceContractResolver : DefaultContractResolver
{
    private readonly Type[] _interfaceTypes;
 
    private readonly ConcurrentDictionary<Type, Type> _typeToSerializeMap;
 
    public InterfaceContractResolver(params Type[] interfaceTypes)
    {
        _interfaceTypes = interfaceTypes;
 
        _typeToSerializeMap = new ConcurrentDictionary<Type, Type>();
    }
 
    protected override IList<JsonProperty> CreateProperties(
        Type type,
        MemberSerialization memberSerialization)
    {
        var typeToSerialize = _typeToSerializeMap.GetOrAdd(
            type,
            t => _interfaceTypes.FirstOrDefault(
                it => it.IsAssignableFrom(t)) ?? t);
 
        return base.CreateProperties(typeToSerialize, memberSerialization);
    }
}

Wednesday, September 16, 2015

Add Generated Files to your Project

I recently had to work with a small code generator and needed to dynamically add generated cs files to my csproj. This actually ended up being very simple!

You will need to use ProjectCollection in the Microsoft.Build assembly to load the project, and then once you have scanned the directory for files you can easily diff the two to find new files. The only "catch" is that you need be sure to match the files to the relative paths from the csproj.

Code

Here is a very simple sample console application that adds generated files to another csproj. (See the picture to the right for the exact file structure.)

public static void Main()
{
    const string relativePath = "../../../TestProj/";
 
    var files = Directory
        .GetFiles(relativePath + "Generated", "*.cs")
        .Select(r => r.Replace(relativePath, string.Empty));
 
    using (var engine = new ProjectCollection())
    {
        var project = engine.LoadProject(relativePath + "TestProj.csproj");
 
        var newFiles = files
            .Where(f => !project.Items.Any(i => i.UnevaluatedInclude == f))
            .ToList();
 
        foreach (var newFile in newFiles)
        {
            project.AddItem("Compile", newFile);
        }
 
        project.Save();
    }
}

Enjoy,
Tom

Real Time Web Analytics