Using Dependency Injection with Startup.cs in ASP.NET Core

Full source code available here.

Did you know that .NET Core 2 can pass in an instance of any type you want to the Startup.cs constructor? Well you can! Here’s how.

Out of the box the Startup.cs comes like this –

public class Startup
{
	public Startup(IConfiguration configuration)
	{
		Configuration = configuration;
	}
//snip..

The IConfiguration is passed in by dependency injection. In Program.cs you can add other types to the DI container, and then add that type to the constructor parameters of Startup.cs.

Here’s how it works. The Microsoft.AspNetCore.Hosting.WebHostBuilder has a ConfigureServices(...) method –

public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
{
    if (configureServices == null)
    {
        throw new ArgumentNullException(nameof(configureServices));
    }

    return ConfigureServices((_, services) => configureServices(services));
}

This lets you add services to the dependency injection container from the Program.cs.

WebHost.CreateDefaultBuilder(args) returns an IWebHostBuilder and that lets you use the ConfigureServices(...) method. Easy!

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureServices(serviceCollection =>
            serviceCollection.AddScoped<ISomeService, SomeService>())
        .UseStartup<Startup>()
        .Build();

And in Startup.cs

public class Startup
{
    private ISomeService _someService;
    public Startup(IConfiguration configuration, ISomeService someService)
    {
        _someService = someService;
        Configuration = configuration;
    }
// snip..	

The instance of ISomeService is of course available for DI everywhere in the application.

public class ValuesController : Controller
{
    private readonly ISomeService _someService;
    public ValuesController(ISomeService someService)
    {
        _someService = someService;
    }
}

Full source code available here.

Getting .NET Core 2.1 Preview 2 Working with Visual Studio 2017

About a year ago I wanted to start using .NET Framework 4.7, it should have been an easy process, but wasn’t. After some trial and error if figured it out and wrote a blog post explaining how to get it working.

Now with the release of .NET Core 2.1 Preview 2, I have hit the familiar problems – no obvious instructions from Microsoft, no one place to download all everything that needed and a Visual Studio install that does not include what you the latest SDK or runtime, and errors like – The specified framework 'Microsoft.AspNetCore.App', version '2.1.0-preview2-final' was not found. or, 'dotnet.exe' has exited with code -2147450730 (0x80008096).

After a few hours messing around and installing the wrong versions of the right software I figured it out.

Step 1

Install the latest version of Visual Studio Preview https://www.visualstudio.com/vs/preview/, at the time of writing this was version 15.7.0 Preview 4.0

I’m interested in developing Web API applications, so I check that box.

BUT, version 15.7.0 Preview 4.0 comes with .NET Core Version 2.1.0 Preview 1. So you don’t get the fancy new features like HttpClientFactory. Read on…

Step 2

Go to
https://github.com/dotnet/core/blob/master/release-notes/download-archives/2.1.0-preview2-download.md and download the SDK and the Runtime for your architecture.

You can verify the checksum of the downloads if you want to by comparing your SHA sum to these ones – https://dotnetcli.blob.core.windows.net/dotnet/checksums/2.1.300-preview2-008530-sdk-sha.txt

Install both the SDK and the runtime.

Step 3

To verify that that you are running .NET Core Preview 2, open visual studio and create a new .NET Core Web API application.

Once it has been created, open the .csproj file, you should see this block –

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0-preview2-final" />
</ItemGroup>

If you don’t see Version="2.1.0-preview2-final", something has gone wrong.

You can verify what packages are installed by going to your start menu and opening Apps and Features/Add or remove programs.

If you have installed the right SDK and runtime you should see the following –

Setting the Kestrel Port From Appsettings.json

Full source code available CoreWithKestrelFromConfighere.

In my previous post I explained how to host Kestrel web server running on (the default) port 5000 as a Windows service. But what if you want to run the server on a different port?

There are a few ways to do this, but the easiest is to add an entry to the appsettings.json file specifying the urls the server should listen to.

In this example, I’m setting it to http://localhost:62000.

The appsettings.json file looks like this –

{
"urls": "http://localhost:62000/"
}

I also removed applicationUrl setting from the from the launchSettings.json file, now Visual Studio and the command line will set the application to the same port.

To add the settings in appsettings.json to the configuration, call .AddJsonFile("appsettings.json") when creating the ConfigurationBuilder.

public class Program
{
    public static IConfiguration Configuration { get; set; }
    public static void Main(string[] args)
    {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json");
        Configuration = builder.Build();

        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseConfiguration(Configuration)
            .Build();
}

You don’t have name the file appsettings.json, you can put it any file you like, but this is convenient.

To run the application from the command line you can do one of two things –

1. Go to the directory where the csproj file is located and type:
dotnet run

2. Go to the bin\debug\netcoreapp2.0 directory and type:
dotnet CoreWithKestrelFromConfig.dll

You can set Kestrel to listen on multiple urls, the format is this –

{
   "urls": "http://localhost:62000/;http://localhost:62002/"
}

Full source code available CoreWithKestrelFromConfighere.

Hosting a .NET Core 2 Kestrel Server in a Windows Service

Full source code available here.

If you have been using the Kestrel web server with Framework 4.x, you might already be hosting Kestrel inside a Windows service. But what if you want to use Kestrel with .Net Core 2? It’s not straightforward to host that with a Windows service, but not too difficult either.

Before installing the service verify that Kestrel is running on the port you expect.

Navigate to

bin\debug\netcoreapp2.0

and type

dotnet WebApiCoreWithKestrel.dll (or whatever the name of your assembly is).

This command should start a console and at the top will be the port Kestrel is running on. If you haven’t specified anything, it will start on port 5000. I’ll show you how to change that in a later post.

Here are the steps for deploying this application as a service.

Step 1
First you need to download nssm, the Non-Sucking Service Manager and place it somewhere in your path or drop the nssm.exe into the bin\debug\netcoreapp2.0 directory of your project (you should use the release dll when deploying for real).

Step 2
Then you build you application.

Step 3
Create a good old batch file to run your dll and add one line –

dotnet WebApiCoreWithKestrel.dll

Swap in whatever the name of your application is.

Step 4
From a command prompt type –
nssm install MyKestrelService

In the nssm window, click on the button to the right of path and pick the startup.bat file you created in step 3.

Click through to the Shutdown tab.

Note the Generate Control-C on shutdown. In Program.cs I’ve added a method that logs when the shutdown signal is received, you of course can perform any task you wish.

private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
    Log.Information("Shutting down");
}

Click Install Service

Step 5
In service manager you should now see a service called MyKestrelService, right click it and start the service.

That’s it your Kestrel server is up and running, you can hit by going to http://localhost:5000/api/values.

Full source code available here.

Entity Framework Core, Calling Stored Procedures and Returning to a Model

Full source code available here.

I wrote a post some time back about calling a stored procedure with Entity Framework using the DbCommand, but it was a bit complicated and not that easy to use.

There is now a FromSql method, you just pass the name of the stored procedure and the parameters. The method returns the results and maps them into a model that matches.

First step is to examine what the stored proc returns. I’m using the NorthWind database and its CustOrderHist stored procedure, its output looks like this – I know from the stored proc that this is a string and int.

I created a class to match –

public class OrderHistory
{
    private OrderHistory() { }

    public int Total { get; private set; }
    public string ProductName { get; private set; }
}

In Entity Framework Core 2 you can call the stored proc like this –

List<OrderHistory> orderHistoryList = await _northwindContext.OrderHistory.FromSql($"EXECUTE dbo.CustOrderHist {customerId}").ToListAsync();

In earlier versions you can use this –

List<OrderHistory> orderHistoryList = await _northwindContext.OrderHistory.FromSql("EXECUTE dbo.CustOrderHist {0}", customerId).ToListAsync();

Full source code available here.

The Circuit Breaker pattern with Polly

Full source code available here.

This post on the Polly circuit breaker is part of a larger series of post on the Polly Resilience Framework, see here for the others, or check out my Pluralsight course.

Basics
The circuit breaker controls the flow of requests from a source to one or more downstream system and cuts the connection when some failure condition is met and resumes the connection after a period. This lets us fail quickly when we know that some remote endpoint or host is not responding as we expect to requests. In this post I am only dealing with the basic circuit breaker, I’ll post another about the advanced circuit breaker later.

Benefits of a circuit breaker

  • Stops requests to the downstream system
  • Reduces load on a failing downstream system, giving it a chance to recover
  • The circuit breaker immediately returns an an error informing the source system that the circuit is open, the source system doesn’t have to wait for a timeout to occur
  • The application with the circuit breaker does not resource like memory, ports and threads when

Background and Terminology
The name, circuit breaker, comes from electrical circuit breakers in your home or office, in some countries these are referred to as trip switches. If the electrical system is working correctly, the circuit is closed and electricity flows to outlets and appliances. But if something goes wrong, the circuit opens, preventing electricity from flowing, thus protecting people and appliances.

The Polly circuit breaker has the corresponding closed and open positions. When closed, the circuit breaker allows requests to be sent, when open, nothing can be sent and an exception is immediately thrown if a request is send to the circuit breaker.

The Polly circuit breaker has one more status, half-open. When in this state Polly will allow the next request to be sent, and if it succeeds the circuit is closed (and normal operation resumes), but if it fails the circuit returns to open (preventing requests from being sent).
The circuit transitions from closed to open when the failure condition is met, from open to half-open when the specified break time is reached.

Here is the full set of possible transitions:
Closed to open – when the failure condition occurs
Open to half-open – when the duration of break is reached
Half-open to closed – when the first request is a success
Half-open to open – when the first request is a failure

The Policy
When creating a circuit breaker policy you specify the condition under which the circuit opens (breaks) and for how long. To be of any use the same instance of the policy must be used across multiple requests, so you cannot just instantiate it inside a controller.

This has implications, if you use the same circuit breaker policy when calling multiple downstream systems, if the circuit breaks for one, it breaks for all.
On the other hand, if you use a circuit breaker on just one downstream system, it can only break the circuit for that one.

I recommend passing policies into the controllers with dependency injection, in the example below I add the policy directly to the DI container, but you should consider using the Polly registry.

As mentioned above the circuit breaker opens when a specified failure condition is met. In the example policy the condition is two consecutive failure responses, the policy also specifies the duration of the break, in this case 10 seconds.

CircuitBreakerPolicy<HttpResponseMessage> breakerPolicy = Policy
    .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .CircuitBreakerAsync(2, TimeSpan.FromSeconds(10), OnBreak, OnReset, OnHalfOpen);

The policy is passed into the DI container this way –

In the controller, assign the circuit breaker to a local variable.

private readonly CircuitBreakerPolicy<HttpResponseMessage> _breakerPolicy;

public CatalogController(HttpClient httpClient, CircuitBreakerPolicy<HttpResponseMessage> breakerPolicy)
{
    _breakerPolicy = breakerPolicy;
    _httpClient = httpClient;
}

Then use it to make calls to the downstream systems, here –

[HttpGet("{catalogId}/inventory")]
public async Task<IActionResult> Get(int catalogId)
{
    string inventoryEndpoint = $"inventory/{catalogId}";

    HttpResponseMessage inventoryResponse = await _breakerPolicy.ExecuteAsync(
             () => _httpClient.GetAsync(inventoryEndpoint));

    //snip..
}

And here –

[HttpGet("{catalogId}/price")]
public async Task<IActionResult> GetPrice(int catalogId)
{
    string requestEndpoint = $"price/{catalogId}";

    HttpResponseMessage pricingResponse = await _breakerPolicy.ExecuteAsync(
            () => _httpClient.GetAsync(requestEndpoint));

    //snip..
}

Full source code available here.

Using an mdf file database with Entity Framework Core 2 in Visual Studio 2017

Full source code available here.

If you want to play around with Entity Framework it can be a little frustrating to create a complex database with a lot of sample data.
Instead, you could download the Northwind database from Microsoft, it has plenty of tables, a bunch of views and handful of stored procs. More than enough to try out many of the features of EF.

Now, all you have to is figure out how to get access to the db from your application, and it’s not as simple as you might hope.
So here’s how to do it in Visual Studio 2017.

Step 1
Download the Northwind database – you can get it here https://www.microsoft.com/en-us/download/details.aspx?id=23654
Install it, it will create some files in c:\SQL Server 2000 Sample Databases.

Step 2
Copy Northwind.mdf and Northwind.ldf to your user directory, something like c:\users\bryan. The Northwind files have to be in that directory to work with the connection string below.

Step 3
Now in Visual Studio use the following connection string.

"Data Source=(LocalDB)\\MSSQLLocalDB;DataBase=Northwind;Integrated Security=True;Connect Timeout=30"

My sample application is a .NET Core Web Api. In startup.cs, add the following –

public void ConfigureServices(IServiceCollection services)
{
	services.AddDbContext<NorthwindContext>(options =>
		options.UseSqlServer("Data Source=(LocalDB)\\MSSQLLocalDB;DataBase=Northwind;Integrated Security=True;Connect Timeout=30"));
	services.AddMvc();}

If you want to place the database files elsewhere in your filesystem, add an absolute filepath to the connection string.

Step 4
Add an Order.cs class, this represents the orders table from the Northwind database. You can of course add more classes to represent other tables in the Northwind database.

public class Order
{
	public int OrderId { get; set; }
	public string CustomerID { get; set; }
	public int EmployeeID { get; set; }
	public DateTime OrderDate { get; set; }
	// etc.
}

Step 5
Add a NorthwindContext class that inherits from DbContext and add the Order DbSet.

public class NorthwindContext : DbContext
{
	public NorthwindContext(DbContextOptions options) : base(options) { }
	public DbSet<Order> Orders { get; set; }
}

Step 6
In the controller, add the NorthwindContext to the constructor.

public OrdersController(NorthwindContext northwindContext)
{
	_northwindContext = northwindContext;
}

Step 7
And finally, use the context in the Get method.

[HttpGet("{orderId}")]
public async Task<IActionResult> Get(int orderId)
{
	var order = await _northwindContext.Orders.Where(o => o.OrderId == orderId).SingleOrDefaultAsync();
	return Ok(order);
}

Full source code available here.

Performing a WHERE IN with Entity Framework or on a List

WHERE IN is a very useful and commonly used feature of SQL, it looks like this –

SELECT * FROM ORDER WHERE OrderId IN (10248, 10249, 10250, 10251)

The will return up to four rows of data, showing just the orders that have an OrderId in the list you passed to the select statement.

You can do the same with Entity Framework by using the Contains predicate with a Where.

First you need to put the OrderIds you are looking for in some sort of enumerable.

IEnumerable ordersToFind = new List { 10248, 10249, 10250, 10251 };

Then you use Where on the Orders DbSet and check the orderIds against the list you just created.

var orders = _northwindContext.Orders.Where(o => ordersToFind.Contains(o.OrderId));

That’s all there is too it. You don’t have to use this on just Entity Framework, it also works on simple lists, arrays, enumerables, etc.

Using the HttpClientInterception to Test Methods That Use a HttpClient

Full source code available here.

In my previous post I showed a way of testing a controller that uses a HttpClient.

I had to mock the HttpMessageHandler pass that to the HttpClient and set a bunch of properties. It works well, but is a bit long winded.

I received a comment from a reader who suggested that I try the JustEat.HttpClientInterception library. It allows you to setup responses to specified requests, and pass these to a HttpClient. Then the HttpClient is passed to the controller.

Here is how the test method looks –

[Fact]
public async Task GetTest()
{
    //Arrange
    List<int> myList = new List<int>() {1, 2, 3, 4, 5};
    
    // setup the interceptor
    HttpRequestInterceptionBuilder builder = new HttpRequestInterceptionBuilder()
        .ForHost("localhost.something.com")
        .ForPath("/v1/numbers")
        .WithJsonContent(myList);
    
    // create the HttpClient from the builder
    // and setup the HttpClientBaseAddress
    HttpClient client = new HttpClientInterceptorOptions()
        .Register(builder).CreateHttpClient("http://localhost.something.com/v1/");

    ValuesController controller = new ValuesController(client);

    //Act
    IActionResult result = await controller.Get();

    //Assert
    OkObjectResult resultObject = result as OkObjectResult;
    Assert.NotNull(resultObject);

    List<int> numbers = resultObject.Value as List<int>;
    Assert.Equal(5, numbers.Count);
}

Briefly, here is the constructor of the values controller. It takes the HttpClient as a parameter, usually passed by dependency injection.

public class ValuesController : Controller
{
    readonly IAsyncPolicy<HttpResponseMessage> _httpRetryPolicy;
    private readonly HttpClient _httpClient;

    public ValuesController(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
	//snip..

Full source code available here.

Unit Testing a Method That Uses HttpClient

Full source code available here.

In this post I’m going to show you how test an action method of controller that uses a HttpClient. When performing this test you want to isolate just the code of the action method for testing, you want to remove the dependency on the HttpClient. I hoped it would be simple, that there would be an IHttpClient, but there is not.

Instead I mocked the HttpMessageHandler, then pass it to the constructor of the HttpClient. The HttpMessageHandler is set to return a list of numbers in response to any request.

The constructor of the controller takes the HttpClient as a parameter, usually passed by dependency injection.

public class ValuesController : Controller
{
    readonly IAsyncPolicy<HttpResponseMessage> _httpRetryPolicy;
    private readonly HttpClient _httpClient;

    public ValuesController(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
	//snip..

In the test class I mock the HttpMessageHandler, set its SendAsync method to return OK and a list of numbers in response to any request. I then pass the mocked HttpMessageHandler to the constructor of the HttpClient.

Now the HttpClient will return the list of numbers I expect and I my test just tests the code of the action method.

The rest of the test is written as normal.

[Fact]
public async Task GetTest()
{
    //Arrange
    string numberJson= JsonConvert.SerializeObject(new List<int>() { 1, 2, 3, 4, 5 });

    var httpMessageHandler = new Mock<HttpMessageHandler>();
    httpMessageHandler.Protected()
        .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
            ItExpr.IsAny<CancellationToken>())
        .Returns(Task.FromResult(new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent(numberJson, Encoding.UTF8, "application/json"),
        }));

    HttpClient httpClient = new HttpClient(httpMessageHandler.Object);
    httpClient.BaseAddress = new Uri(@"http://localhost:63781/v1/");
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    ValuesController controller = new ValuesController(httpClient);

    //Act
    IActionResult result = await controller.Get();

    //Assert
    OkObjectResult resultObject = result as OkObjectResult;
    Assert.NotNull(resultObject);

    List<int> numbers = resultObject.Value as List<int>;
    Assert.Equal(5, numbers.Count);
}

Full source code available here.