Using IConfiguration and appsettings.json in a .NET Core Azure Function project

For very basic Web APIs, HTTP triggered Azure functions are a very efficient and cost effective way to implement the service. One inconvenience though is that by default it does not come hooked up with an appsettings.json file or an IConfiguration instance. Fortunately, it’s not very difficult to hook those up.

Step 1

Add the following NuGet package to your project.

  • Microsoft.Azure.Functions.Extensions

Step 2

Add a startup.cs file to your project and insert the following code.

[assembly: FunctionsStartup(typeof(Startup))]

public class Startup : FunctionsStartup
{
    public override void ConfigureAppConfiguration(
      IFunctionsConfigurationBuilder builder)
    {
        var context = builder.GetContext();

        builder.ConfigurationBuilder
            .AddJsonFile(
              Path.Combine(
                context.ApplicationRootPath, 
                "appsettings.json"), 
              optional: true, 
              reloadOnChange: false)
            .AddJsonFile(
              Path.Combine(
                context.ApplicationRootPath, 
                $"appsettings.{context.EnvironmentName}.json"), 
              optional: true, 
              reloadOnChange: false)
            .AddEnvironmentVariables();
    }
}

Step 3

Add your appsettings.json file and setup any configuration properties you need in there.

{
  "YourProperty": "some-value-here"
}

Step 4

Inject IConfiguration into your constructor. Note that the default function template won’t have a constructor as it uses a static class. Remove the static, and add the constructor.

private readonly IConfiguration _configuration;

public SomeFunction(IConfiguration configuration)
{
    _configuration = configuration;
}

And now you can use it in the function as you’d normally do.

[FunctionName("SomeFunction")]
public async Task<IActionResult> Run(
    [HttpTrigger(
      AuthorizationLevel.Anonymous, 
      "get", 
      "post", 
      Route = null)] 
    HttpRequest req,
    ILogger log)
{
  // Use _configuration["YourProperty"]
}

Using Newtonsoft JsonConvert to easily construct a derived class from a base instance

Okay, so this may not be the most efficient code – so you may not want to use this in a context where milli seconds matter. But say you have a model class (returned by another library or from an API) and you need to extend it by adding a single property to it. The simplest way to do this is to derive a new class, add the property to it and then to add a constructor that copy-constructs from base to derived. Bit of a hassle having to copy every single property though, although I’d imagine some of those new AI powered IDEs could auto-generate code for you. Even then, if the base class ever changes, you will need to update this constructor and if you forget to do that, there’s a risk of random buggy behavior. So, what’s the hack? Use JsonConvert to serialize the base object, then deserialize it to derived and then populate the new field or fields that’s been added to derived.

static void Main()
{
    ModelEx model = Foo(new Model
    {
        Id = 1000,
        Name = "Mary Miller",
        Description = "Senior Accountant"
    });
    model.Enabled = true;
}

private static ModelEx Foo(Model model)
{
    var json = JsonConvert.SerializeObject(model);
    return JsonConvert.DeserializeObject<ModelEx>(json);
}

class ModelEx : Model
{
    public bool Enabled { get; set; }
}

class Model
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

3 lines of code for an ASP.NET Web API

Okay, this is admittedly a bit of a frivolous post. That said, with just these 3 lines of code, you will have a REST API up and running.

var app = WebApplication.Create();
app.MapGet("/", () => $"Running @ {DateTime.UtcNow}");
await app.RunAsync();

Line 1 instantiates your web app instance, the 2nd line adds your one endpoint, and the last one starts the web app (http listener).

Exiting an Azure WebJob programmatically

If you need your WebJob to run a task and exit, or if you need to conditionally exit it under certain scenarios, and you thought it’s just a matter of exiting the worker service’s ExecuteAsync method, you’d be wrong. Even after your worker code has stopped running, the parent host stays alive. The right way to exit your WebJob is to inject IHostApplicationLifetime into your worker, and then the last line of code in your ExecuteAsync would be a call to its StopApplication method.

public Worker(ILogger<Worker> logger, IHostApplicationLifetime appLifeTime)
{
    _logger = logger;
    _appLifetime = appLifeTime;            
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    int runs = 0;

    while (!stoppingToken.IsCancellationRequested && runs++ < 3)
    {
        // do some task here   
        await Task.Delay(2000, stoppingToken);
    }

    _appLifetime.StopApplication();
}

Azure WebJobs not logging to Application Insights

With regular App Services, if you enabled Application Insights, your ILogger logs will get written into Application Insights without having to do anything special. This is not the case with WebJobs though. After wasting a few hours trying to figure out why my logs were not showing up, here’s a solution I found that worked.

Step 1

Install the latest version of Microsoft.Azure.WebJobs.Logging.ApplicationInsights.

Step 2

Modify your startup code as follows.

public static void Main(string[] args)
{
    IHost host = Host.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
        {
            services.AddHostedService<Worker>();
        })
        .ConfigureLogging((context, builder) =>
        {
            builder.AddConsole();

            var key = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
            if (!string.IsNullOrEmpty(key))
            {
                builder.AddApplicationInsightsWebJobs(
                    options => options.InstrumentationKey = key);
            }
        })
        .Build();

    host.Run();
}

And that’s it. Remember that there’s usually a 1-2 minute delay before your logs show up in App Insights, and it could be as high as 3-4 minutes if it’s the first time you deploy. So, don’t panic if you don’t see the logs right away. Happy debugging!

Serializing enums as strings

Enumerations in C# are ints by default, which is fine most of the time. That said, there are situations where you’d want to store and retrieve them using their string names, especially when you are persisting them to a database. The string names make them more readable for one reason. For another, a re-ordering of the enums (caused inadvertently by the addition or removal of an entry) would change their int values, which can potentially break your data when reading them back from a database. Consider the following types – Model and Seasons.

enum Seasons
{
    Spring,
    Summer,
    Fall,
    Winter
}

class Model
{
    public string Name { get; set; } = String.Empty;

    public Seasons Season { get; set; }
}

If you serialize an instance of Model, you’d see the int value for the Season property.

var model = new Model
{
    Name = "Test Model",
    Season = Seasons.Fall,
};

var json  = JsonConvert.SerializeObject(model, Formatting.Indented);
Console.WriteLine(json);

Output looks like this.

{
  "Name": "Test Model",
  "Season": 2
}

It’s fairly easy to change this behavior though. Just add a JsonConverter attribute to the Season property.

class Model
{
    public string Name { get; set; } = String.Empty;

    [JsonConverter(typeof(StringEnumConverter))]
    public Seasons Season { get; set; }
}

Output is now nice and clean.

{
  "Name": "Test Model",
  "Season": "Fall"
}

You get the same behavior both when serializing and deserializing, and the latter is important when reading data back from a database.

How about if you have a collection of enums though? That’s simple too, just replace the JsonConverter attribute with the following JsonProperty attribute.

class Model
{
    public string Name { get; set; } = String.Empty;

    [JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
    public List<Seasons> Seasons { get; set; } = new List<Seasons>();
}

Output is as expected.

{
  "Name": "Test Model",
  "Seasons": [
    "Fall",
    "Winter"
  ]
}

C# and the need (lack of) for move semantics

Someone recently asked me why C# does not support move semantics. Well, C# mostly deals with references, so you don’t have to to deal with copy constructors called on temporary objects. C# does support value types too but they are nearly always used for POD (plain old data) types. And when there is the need for a copy, what’s usually done is to implement an interface such as ICloneable. In the C# (and .NET) world, assignments are mostly reference copies. A reference variable takes the value of another reference variable. In summary, C# as a language does not have a need for move semantics.

Validating a bit flags enum value

This was recently asked in the Code Project Q/A forums, and while there were several responses posted, I think the following is succint and works well.

private static bool IsValidFlagValue<T>(int x) where T : struct
{
    int aggregate = Enum.GetValues(
      typeof(T)).Cast<int>().Aggregate((z, y) => z | y);
    return x <= aggregate && (aggregate & x) > 0;            
}

Note that it does not handle a case where the flag-enum has a 0-value. Here’s a version that does that too (a little less brief).

private static bool IsValidFlagValue<T>(int x) where T : struct
{
    var values = Enum.GetValues(typeof(T)).Cast<int>();
    if (x == 0 && values.Contains(0))
    {
        return true;
    }

    int aggregate = values.Aggregate((z, y) => z | y);
    return x <= aggregate && (aggregate & x) > 0;            
}

Using Socket.Disconnect(true)

Recently, someone asked this question on the CodeProject forums where the OP wondered if reusing the socket would mean he’d get the same client endpoint. This is the gist of my response to him.

Calling Socket.Disconnect(true) will internally result in Winsock’s DisconnectEx function being called with the TF_REUSE_SOCKET parameter.

From the docs:

Prepares the socket handle to be reused. When the DisconnectEx request completes, the socket handle can be passed to the AcceptEx or ConnectEx function.

So it’s only the socket handle that will be reused. This has nothing to do with your local endpoint.

Socket reuse is meant for fairly advanced use, where you know exactly what you are doing. It’s typically used in high performance heavy traffic TCP servers. The idea being that by reusing a socket, you save some time (the time that would normally have gone into allocating that socket and its resources). So what some server developers do is to have a pre-created socket pool that they pull sockets from as and when required.

So in my opinion, for a client side TCP application there is never a good reason to reuse a socket.

In short, always use Socket.Disconnect(false) unless you really know what you are doing.

For some reason, this is not so well documented and leads to a lot of confusion.

What about static indexers in C#?

Well, that’s not really possible but often people do ask if they can do this. Here’s a solution I recently gave someone which comes quite close which uses a singleton class instead of a static one:

class Test
{
    static Dictionary<int, string> map = new Dictionary<int, string>();

    private Test() { }

    private static Test instance = new Test();

    internal static Test Instance
    {
        get { return Test.instance; }
    }

    public string this[int i]
    {
        get
        {
            return map[i];
        }

        set
        {
            map[i] = value;
        }
    }
}

And here’s how you would use this:

Test.Instance[3] = "hello";
string s = Test.Instance[3];