Calling a Web API from a Console App and Creating a Performance Test

While working on a proof of concept, I needed to create a dummy API, and then run a stress test on it. Whilst the activity itself may seem pointless (creating a templated API and stress testing it), I felt the process might be worth documenting.

Create the API

We’ll start with creating the API:

dotnet new webapi

If you just run this, you should see the following:

The next step is to call that from a console app.

Create a console app to call the API

Add a new console app project to your solution, and replace the code in Program.cs with the following:

    class Program
    {
        static HttpClient client = new HttpClient();
        static string path = "https://localhost:44356/weatherforecast";


        static async Task Main(string[] args)
        {
            Console.WriteLine("Press enter to start test");
            Console.ReadLine();
            string? data = await CallWeatherForecast();

            Console.WriteLine(data ?? "No data returned");
        }

        private static async Task<string?> CallWeatherForecast()
        {            
            HttpResponseMessage response = await client.GetAsync(path);
            if (response.IsSuccessStatusCode)
            {
                string data = await response.Content.ReadAsStringAsync();
                return data;
            }

            return null;
        }
    }

It’s worth noting that I switched on nullable reference types here (in the csproj file):

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

To test this, you’ll need to start both the projects (either select Set Startup Projects… from the solution context menu, or run the API, and then right-click the console app and select Debug -> Start New Instance).

Once you’ve checked that this works, build the solution in release mode (remember, we’re going to be running a stress test, so debug mode will show skewed results).

Call the console app from JMeter

For the stress test, I’m going to use Jmeter. You’ll need to download it from here.

I won’t go into too much detail about how to set this up, but briefly, extract the downloaded zip somewhere, and run the jmeter.bat file. You should be presented with the following screen:

Add a thread group, so we can simulate multiple users:

Then add an OS Process Sampler to run the console app:

Remember to run the API first, then click the green play arrow. You’ll see the users ramp up:

We don’t have any listeners, so the results are, unfortunately lost. Let’s add a couple:

As you can see, we now have some information. How long these calls are taking on average, the error count, etc. The throughput we’re getting is around 3/second… In fact, running a stress test locally on the same machine, it’s difficult to break it, because as the resources get used up, the JMeter process itself suffers, too. This is a good reason to run JMeter from a VM in the cloud.

Whilst it’s quite difficult to kill the service, I certainly managed to slow it down considerably:

These figures are in milliseconds, which means that 90% of calls are taking over 2 minutes. This entire test took around 15 minutes, and around 10 requests per second was about the best it got to (I ran 10 loops of 1000 concurrent users).

There’s a few things you can do to identify where the performance starts to degrade, but I’m more interested in what happens to these figures if I add DB access.

Note: when you’re playing with this, the reports don’t automatically clear each run, so you have to select each, right-click and clear.

Add calls to a DB

Let’s add Entity Framework to our project.

We can then change the controller to allow adding new records and retrieval by date:

        public WeatherForecastController(
            ILogger<WeatherForecastController> logger,
            StressTestDbContext stressTestDbContext)
        {
            _logger = logger;
            _stressTestDbContext = stressTestDbContext;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> GetNew()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
        
        [HttpGet("/[controller]/GetByDate/{dateTime}")]
        public IEnumerable<WeatherForecast> GetByDate(DateTime dateTime)
        {
            var forecasts = _stressTestDbContext.Forecast.Where(a => a.Date.Date == dateTime.Date);
            return forecasts;
        }

        [HttpPost]
        public IActionResult Post(WeatherForecast weatherForecast)
        {
            DailyForecast forecast = new DailyForecast()
            {
                Date = weatherForecast.Date,
                Summary = weatherForecast.Summary,
                TemperatureC = weatherForecast.TemperatureC
            };

            _stressTestDbContext.Add(forecast);
            if (_stressTestDbContext.SaveChanges() != 0)
            {
                return Ok();
            }
            return BadRequest();
        }

Finally, we can change the main program to call those functions:

        static async Task Main(string[] args)
        {
            Console.WriteLine("Press enter to start test");
            Console.ReadLine();

            ConsoleTitle("CallGetNewWeatherForecast");
            string? dataGet = await CallGetNewWeatherForecast();
            Console.WriteLine(dataGet ?? "No data returned");

            ConsoleTitle("AddForecast");
            string? dataAdd = await AddForecast(_rnd.Next(30),
                DateTime.Now.AddDays(_rnd.Next(10)), _summaries[_rnd.Next(_summaries.Length)]);
            Console.WriteLine(dataAdd ?? "No data returned");

            ConsoleTitle("CallGetWeatherForecast");
            string? dataGetDate = await CallGetWeatherForecast(DateTime.Now.AddDays(_rnd.Next(10)));
            Console.WriteLine(dataGetDate ?? "No data returned");
        }

        private static void ConsoleTitle(string title)
        {
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine(title);
            Console.ResetColor();
        }

        private static async Task<string?> CallGetNewWeatherForecast()
        {            
            HttpResponseMessage response = await client.GetAsync($"{path}");
            if (response.IsSuccessStatusCode)
            {
                string data = await response.Content.ReadAsStringAsync();
                return data;
            }

            return null;
        }

        private static async Task<string?> CallGetWeatherForecast(DateTime dateTime)
        {
            string dateString = dateTime.ToString("yyyy-MM-dd");

            HttpResponseMessage response = await client.GetAsync($"{path}/GetByDate/{dateString}");
            if (response.IsSuccessStatusCode)
            {
                string data = await response.Content.ReadAsStringAsync();
                return data;
            }

            return null;
        }

        private static async Task<string> AddForecast(int temperature, DateTime date, string summary)
        {
            var forecast = new WeatherForecast()
            {
                TemperatureC = temperature,
                Date = date,
                Summary = summary
            };

            HttpResponseMessage response = await client.PostAsJsonAsync($"{path}", forecast);
            if (response.IsSuccessStatusCode)
            {
                string data = await response.Content.ReadAsStringAsync();
                return data;
            }

            return null;
        }

To get a sensible reading, you’ll need to do this from an empty database:

For the first run, we’ll do 500 users, and 3 iterations:

The output from the first run is:

And let’s just check that that’s created the records we expected:

EF async calls vs non-async

To satisfy a curiosity that I’ve had for a while, I’m now going to change the update API method to async:

        [HttpPost]
        public async Task<IActionResult> Post(WeatherForecast weatherForecast)
        {
            DailyForecast forecast = new DailyForecast()
            {
                Date = weatherForecast.Date,
                Summary = weatherForecast.Summary,
                TemperatureC = weatherForecast.TemperatureC
            };

            _stressTestDbContext.Add(forecast);
            if (await _stressTestDbContext.SaveChangesAsync() != 0)
            {
                return Ok();
            }
            return BadRequest();
        }

Again, 1500 records were created:

Here’s the report:

What an interesting result. Making the update async seems to have slightly reduced the throughput. This is running locally, and I only have a 4 core machine, but I would have expected throughput to slightly increase here, rather than decrease.

Entity Framework 3.1 Gotchas

I’ve recently been upgrading an EF Core 2.x project to EF Core 3.1. In doing so, I came across the issues in this post. Hopefully, next time, I’ll look here first!

Include has changed

If you’re using .include in a lambda that’s based on a DbSet, you may have something akin to the following:

var result = animals
                .Select(a => a.Name)
                .Where(a => a.Type.Name == "Duck")
                .Include(a => a.Type)
                .ToList();

Whilst this does work in EF 2.x, it will not work in 3.x; you’ll may get the following error:

System.InvalidOperationException: ‘Include has been used on non entity queryable.’

The issue here is that you’re restricted as to how you can use Includes. You’ll need to use something more like this:

var ducks = animals
                .Include(a => a.Type)
                .Select(a => a.Name)
                .Where(a => a.Type.Name == "Duck")
                .ToList();

Should you wish to include multiple related entities, you can use the following syntax:

var ducks = animals
                .Include(a => a.Type)
                .ThenInclude(a => a.EnvironmentInformation)
                .Select(a => a.Name)
                .Where(a => a.Type.Name == "Duck")
                .ToList();

Beware of Unions

Unions don’t actually work in Entity Framework Core. They never have. What this means, is that in 2.1, when you issues this type of command:

var ducks = animals
                .Include(a => a.Type)
                .Select(a => a.Name)
                .Where(a => a.Type.Name == "Duck");

var geese = animals
                .Include(a => a.Type)
                .Select(a => a.Name)
                .Where(a => a.Type.Name == "Goose");


var combined = geese
               .Union(ducks);

What actually happened was that the two queries would be run, the results brought down to the client and joined there. In 3.x, you get something like the following error:

System.InvalidOperationException: ‘Set operations over different store types are currently unsupported’

Essentially, what this forces you to do is ether explicitly bring the results down to the client yourself:

var ducks = animals
                .Include(a => a.Type)
                .Select(a => a.Name)
                .Where(a => a.Type.Name == "Duck")
                .ToList();

Or run the query on the server by employing something like a Stored Procedure.

References

https://github.com/dotnet/efcore/issues/18091

Debugging an Asp.Net Core React Application in Azure

I’ve recently been working with an Asp.Net Core ReactJS application. When trying to debug this remotely, I switched on Development mode in order to get a stack trace when it crashed:

Instead of the stack trace, I got this:

An unhandled exception occurred while processing the request. AggregateException: One or more errors occurred. (One or more errors occurred. (The NPM script ‘start’ exited without indicating that the create-react-app server was listening for requests. The error output was: )) System.Threading.Tasks.Task.ThrowIfExceptional(bool includeTaskCanceledExceptions)
InvalidOperationException: The NPM script ‘start’ exited without indicating that the create-react-app server was listening for requests. The error output was:

This is, in fact, caused by the following code:

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (_env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });

This uses the setting “Development” to determine whether to start a local React server; which will fail on a remote server. However, I want to see a stack trace, which is here:

            if (_env.IsDevelopment())            
            {
                app.UseDeveloperExceptionPage();
            }

The problem here is that “Development” has two functions – it displays a stack trace, and it manages all these variables that should only run on your machine. What we need are two settings that both mean “Development”; one that means that we’re running locally, and one that we’re trying to debug. Start with an environment variable:

You can set this to anything you choose… But I’ve gone with “LocalDevelopment”.

The next step is to find all the places that check IsDevelopment, and replace them. What we essentially want is this:

                //if (_env.IsDevelopment())
                if (_env.IsEnvironment("LocalDevelopment"))
                {

However, we can create our own extension method, so that the code looks a lot neater:

        public static bool IsLocalDevelopment(this IWebHostEnvironment env)
        {
            return (env.IsEnvironment("LocalDevelopment"));
        }

Remember that IsEnvironment() is actually an extension method itself, so you would need to include:

using Microsoft.Extensions.Hosting;

In your extension class.

What to change

The following places will, at a minimum, need replacing for a standard web app. The stack trace should be displayed in either situation:

        public void Configure(IApplicationBuilder app)
        {
            if (_env.IsDevelopment() || _env.IsLocalDevelopment())                  
            {
                app.UseDeveloperExceptionPage();
            }

The React check that started all this:

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (_env.IsLocalDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });

Also, if you’re using local secrets, you’ll need this in Program.cs:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder
                        .ConfigureAppConfiguration((hostingContext, config) =>
                        {
                            if (hostingContext.HostingEnvironment.IsEnvironment("LocalDevelopment"))
                            {
                                config.AddUserSecrets<Program>();
                            }

Because, by default, local secrets are only added for Development only.

Summary

That’s it, you can now set the ASPNETCORE_ENVIRONMENT to Development on a remote server, and you should get a stack trace.

Configuration and Dependency Injection

In this post, I wrote about how to mock out the configuration for an application. What I did not cover in that post was whether it was a good idea to pass around IConfiguration. The answer is that, at least in my opinion, it’s a very bad idea.

In this post, I’d like to discuss why I think it’s a bad idea, and my take on a better idea.

Single Responsibility

The first reason is that you are, essentially, breaking the principle of single responsibility. Let’s imagine that we have a class that accepts an IConfiguration as a parameter. When you need an element from the configuration, you have to issue a command like this:

var myValue = new _configuration.GetValue<string>("MyValue");

So, what’s wrong with this? It’s not exactly complex code, and it’s intent is clear. However, your method is now doing two things: it’s doing what it was intended to do, and it’s reading from the configuration. If MyValue changes (say you want to call it “MyNewValue”) then you have to change your method – but your method should not care where, or how this value is retrieved! Let’s say my full class is this:

public class CalculateTemperature 
{
    private IConfiguration _configuration;
    public CalculateTemperature(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public bool IsFreezing(double temperature)
    {
        string scale = _configuration.GetValue<string>("TempScale");
        switch (scale)
        {
            case "Fahrenheit":
                return temperature == 32;

            case "Centigrade":
                return temperature == 0;

            case "Kelvin":
                return temperature == 273;

        }
    }
}

Okay, so I have a class, and a method – the class is responsible for temperature calculations, and the method for telling me if a given temperature is the freezing point of water. However, the IsFreezing method also gets a setting from the configuration file. What this means is that the method above already has a potential bug: what if the setting is not present, or it’s set to some other temperature scale, “Celcius” for example; so you now end up with a method that looks like this:

    public bool IsFreezing(double temperature)
    {
        string scale = _configuration.GetValue<string>("TempScale");
        switch (scale)
        {
            case "Fahrenheit":
                return temperature == 32;

            case "Centigrade":
            case "Celcius":
                return temperature == 0;

            case "Kelvin":
                return temperature == 273;

            case default:
                throw new Exception($"Temperature scale is unsupported");
        }
    }

Buy why should this method have to deal with what’s in the configuration file? A better implementation of this method would be something like this:

    public bool IsFreezing(double temperature, Scale scale)
    {
        switch (scale)
        {
            case Scale.Fahrenheit:
                return temperature == 32;

            case Scale.Centigrade:
                return temperature == 0;

            case Scale.Kelvin:
                return temperature == 273;
        }
    }

Now I can create a config full of ANSI art for all this method cares; and as a result, I can get rid of IConfiguration out of the class.

Testing

The second reason, as I think I implied, is that it is not straight-forward to mock out the IConfiguration class. That fact that I created a blog post on the subject means that it needs one (at least for me), which means it’s far too much hassle; which means that classes and methods that contain this are less likely to be tested.

The Real World

The example I’ve given above isn’t a very realistic example, and I’m sure that no-one reading this would create a method that read from the config for a setting that so clearly relates to the method; however, the following is a very common thing, and I’m sure that you have written something akin to this, somewhere (I know I have):

public class TemperatureRepository
{
    private IConfiguration _configuration;
    public CalculateTemperature(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public bool WasFreezingLastWeek(DateTime dateTime)
    {
        string connectionString = _configuration.GetValue<string>("ConnectionString");

        . . . 
    }
}

The exact same argument applies to this, as did for the method above, but this doesn’t feel so wrong. The reason is that you know what the Startup.cs call looks like when your class looks like this:

public class TemperatureRepository
{
    private string _connectionString;
    public CalculateTemperature(string connectionString)
    {
        _connectionString = connectionString;
    }

    public bool WasFreezingLastWeek(DateTime dateTime)
    {
        . . . 
    }
}

You either need to create the class before you inject it, or do something like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<ITemperatureRepository>(srv => 
    {        
          new  TemperatureRepository(Configuration.GetValue<string>("ConnectionString"));
    });
}

In fact, I don’t think this looks too bad but, recently, I’ve been using a slightly different approach, which allows you to avoid this: that is to register a class that contains your config. If you have three or four values, then maybe have one config class for your entire application; if there’s more then have as many as make sense:

public void ConfigureServices(IServiceCollection services)
{
    var configClass = new ConfigClass()
    {
        ConnectionString = Configuration.GetValue<string>("ConnectionString");
    };

    services.AddScoped<ConfigClass>(configClass);
    services.AddScoped<ITemperatureRepository>();
}

Summary

I’m not sure this warranted such a long blog post, but it’s a Saturday afternoon and the pubs are closed!

Caveat

None of the code in this post has been tested – it’s all been written in OneNote – I didn’t think the specific code syntax was particularly relevant, given it’s more of an opinion post.

Add Storage Queue Message

I’ve written quite extensively in the past about Azure, and Azure Storage. I recently needed to add a message to an Azure storage queue, and realised that I had never written a post about that, specifically. As with many Azure focused .Net activities, it’s not too complex; but I do like to have my own notes on things.

If you’ve arrived at this post, you may find it’s very similar to the Microsoft documentation.

How to add a message

The first step is to install a couple of NuGet packages:

Install-Package Microsoft.Azure.Storage.Common
Install-Package Microsoft.Azure.Storage.Queue

My preference for these kinds of things is to create a helper: largely so that I can mock it out for testing; however, even if you fundamentally object to the concept of testing, you may find such a class helpful, as it keeps all your code in one place.

 public class StorageQueueHelper
{
        private readonly string _connectionString;
        private readonly string _queueName;

        public StorageQueueHelper(string connectionString, string queueName)
        {
            _connectionString = connectionString;
            _queueName = queueName;
        }

        public async Task AddNewMessage(string messageBody)
        {
            var queue = await GetQueue();

            CloudQueueMessage message = new CloudQueueMessage(messageBody);
            await queue.AddMessageAsync(message);
        }

        private async Task<CloudQueue> GetQueue()
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_connectionString);
            CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
            CloudQueue queue = queueClient.GetQueueReference(_queueName);
            await queue.CreateIfNotExistsAsync();

            return queue;
        }
}

The class above works for a single queue, and storage account. Depending on your use case, this might not be appropriate.

The GetQueue() method here is a bit naughty, as it actually changes something (or potentially changes something). Essentially, all it’s doing is connecting to a cloud storage account, and then getting a reference to a queue. We know that the queue will exist, because we’re forcing it to (CreateIfNotExistsAsync()).

Back in AddNewMessage(), once we have the queue, it’s trivial to simply create the message and add it.

References

https://docs.microsoft.com/en-us/azure/storage/queues/storage-tutorial-queues

React, Redux, and Typescript – Why, What and How

This article covers adding Redux to an existing React application.

Redux is one of those technologies where you get introduced to it, and you think: this seems overly complex to solve such a simple problem. Quite often, this is, in fact, the case. I once read a post (which I cannot find) by Dan Abramov where he said a similar thing himself. Redux is a state manager, and if you’re using it for React, React does have facilities to manage its own state, so you may not need Redux.

In fact, from what I’ve seen, I’d say you’re better leaving it until you know you need Redux.

Why

So, how will you know when you need Redux?

Well, you’ll know because you’ll raise some state, and suddenly realise that you’ve raised it into a component that has no business managing that state. My specific example was trying to manage user permissions.

Imagine the following menu structure:

Layout.tsx
	NavMenu.tsx
		NavItem (React-Strap)
		LoginMenu.tsx (accesses the DB to get user info)

I needed to store a user permission, and conditionally display a menu option (NavItem); these are held in a LoginMenu component. This meant that my state would need to be in NavMenu.tsx – but that’s a strange place for the state regarding a user to live. Additionally, other parts of the application would need access to this, and so it’s time for a state manager.

What

Okay, we’ve talked about why you might want to add Redux. Let’s see, exactly what Redux is. Essentially, there are three concepts to Redux. Before I continue with my second rate explanation, I would strongly suggest you jump over to Dave Ceddia’s blog. If you’re trying to do this in Typescript, then come back afterwards – otherwise, stay there, there’s nothing I can tell you that he doesn’t cover in this article.

Actions

An action is simply an object that contains a property called type. It can contain other objects, too, and is used to send information from your application into the Redux Store.

Reducers

Reducers are the engine of Redux. They accept an action, and the existing state of the application, and they return a new state.

Store

The store holds the current application state. You cannot change this directly, but through an action.

How

(In this section, I’ll include some imports and file names – I’ll talk about project structure towards the end, and the imports and filenames will make sense then)

Let’s imagine that your application is a game, where you can move a character left and right; your application state might look like this:

export interface IStore = {
    position: 0
}

We’ll also need to create the store, which we can do in the same code file:

Store.tsx

import { reducer } from '../State/Reducer';
import { createStore } from 'redux';

export interface IStore {
    position: number;
}

const store = createStore(reducer);
export default store;

Okay, so we have a state: we said that actions are the only things that can affect state (in fact we said through an action): let’s see what an action might look like:

export const MOVE = 'MOVE'

interface MoveAction {
    type: typeof MOVE
}

This would be sufficient, at least, this is all Redux needs; however, we need to know which way to move, etc. Convention seems to be to add a payload property; let’s see what that might look like:

Actions.tsx

export const MOVE = 'MOVE'
export interface Message {
    user: string
    message: string
    timestamp: number
  }
  
interface MoveAction {
    type: typeof MOVE
    payload: Message
}
    
export type ActionTypes = MoveAction;

I’ve used a generic Message – you could make this specific to your action, but this sort of approach means that your messages are consistent across actions.

So, now we have a store (somewhere to keep the state), and an action something to indicate that we wish to update the state. However, looking at the action, it doesn’t seem to do too much updating… In fact, it’s just a message – it could even be just a string. We now need the final piece of the jig-saw: the reducer takes the action and updates the state; let’s see what that might look like:

Reducer.tsx

import { InitialState } from './Store';
import { ActionTypes, MOVE } from './Actions';

export function reducer(state = InitialState, action: ActionTypes) {  
    console.log (action);
    switch (action.type) {
      case MOVE:
        return {
            ...state,
            position: state.position + parseInt(action.payload.message)
        }
        
      default:
        return state;
  
    }
    
}

There’s quite a lot here: (we’ll come back to InitialState shortly). Let’s go through a piece at a time.

The first thing we’re doing is checking the type parameter:

    switch (action.type) {
      case MOVE:

In a real world situation, there would be many options: you’re unlikely to have a single action, so the switch statement is necessary.

Remember earlier, we defined the action as MOVE:

export const MOVE = 'MOVE'

Which enables us to check for MOVE, rather than the magic string “MOVE”.

Inside the MOVE block, we’re accessing the payload:

      case MOVE:
        return {
            ...state,
            position: state.position + parseInt(action.payload.message)
        }

The reducer must be a pure function: that is, it accepts and returns data, but it does not change anything; as a result, we’re returning a new version of the state that was passed in. We’re setting the new state to have a position which is based on the current position, but we’re not changing the state.

This code will crash if the message is set to “qwerty” (so if you’re doing this sort of thing yourself, you should do it better than I have!)

Finally, the default: block simply returns the same state that it was given; i.e. the state remains unchanged.

Initial State and Project Structure

I said we’d come back to initial state. In the reducer, we have the following:

export function reducer(state = InitialState, action: ActionTypes) {  

We have to define a starting state for the store; and you can do that like this:

Store.tsx

export const InitialState: IStore = {
    position: 0
}

Before we move onto the application changes, let’s quickly talk about where this all goes. The frustrating answer is, it’s up to you; however, I found a structure like this quite useful, as it keeps all the Redux plumbing in a single place:

Plugging this into your app

So far, we’ve created a lot of code, but it’s been completely separate from your React application. Plugging it in is actually quite trivial. Let’s start with Index.tsx; you’ll need to import your reducer:

import { reducer } from './State/Reducer';

In the render function, you’ll then need to add the store into the DOM:

ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter basename={baseUrl}>
      <App />
    </BrowserRouter>
  </Provider>,
  rootElement);

We can then access the store inside any component by simply referencing the Store.tsx:

import store from '../../State/Store';
import { MOVE } from '../../State/Actions';

And then calling the dispatch function:

            store.dispatch({
                type: MOVE,
                payload: {
                    user: user.name,
                    message: "1",
                    timestamp: new Date().getTime()
                }
            });

We can also get the state by using this:

store.getState();

Connecting the State

This works okay, but there is an easier way; you can use the Redux Connect function. Essentially, instead of exporting the React class, you instead export a wrapper for it. Before that, though, you need to work out what you’re trying to map. You’ll need to split your props into three groups:

1. Props from the store that you want in your component
2. Props that you want to be passed into your component
3. Props from the store that are actually functions; that is, dispatch functions

You would then rewrite your component like this:

import { connect } from 'react-redux';
interface StoreProps {
   position: number;
}
interface OwnProps {
   ...
}
interface DispatchProps {
   ...
}

type Props = OwnProps & StoreProps & DispatchProps;
interface IState {
   ...
}
class GameComponent extends Component<Props, IState> {
   ...

Notice that you’re no longer exporting the GameComponent class. Instead, you add the following:

function mapStateToProps(state: IStore) {
  return {
    position: state.position
  };
}
export default connect(mapStateToProps)(GameComponent);

This allows you to expose only the properties relevant to the component, but not the properties that you take from the Redux store.

References

https://blog.logrocket.com/why-use-redux-reasons-with-clear-examples-d21bffd5835/

https://daveceddia.com/redux-tutorial/

https://daveceddia.com/access-redux-store-outside-react/

https://redux.js.org/recipes/usage-with-typescript

Using Kudu to Edit a Deployed app.settings file

When you deploy an Azure App Service, there are occasions when you may need to change the running values. Exactly how you may do this depends heavily on how the service was deployed, and how you are managing your variables. You can typically overwrite variables inside the app service; however, the running appsettings.json and web.config will be deployed with the app, and you can edit these directly (whether you should or not is a different question).

It’s your foot

These instructions let you change the deployed files on your App Service. Doing so may result in the behaviour of the site changing.

On with the show

Launch Kudu

When you select this, you’ll be given the option to select “Go”, or … not. Select “Go”.

This will take you to the Kudu console.

From here, select “CMD”; this will take you to a hybrid screen with a command console and a file navigator:

Navigate to d:\home\site\wwwroot:

Too Many Files

Initially, you may get the following error:

There are n items in this directory, but maxViewItems is set to 99. You can increase maxViewItems by setting it to a larger value in localStorage.

To get around this, select F12 and in the console window type:

window.localStorage['maxViewItems'] = 1000

After you’ve changed this, refresh the page (F5).

App Settings

To change the variables, you’ll need to locate the appsettings.json in the list (it’s alpha-numerically sorted, so it should be near the top). (Unfortunately, you can’t edit this from the command line).

When you find the file, click the edit button:

And then change the file:

When done, select Save and then restart the app service.

References

https://www.poppastring.com/blog/kudu-error-with-maxviewitems-in-localstorage

Capturing Url Parameters in ReactJS using Typescript

This sounds like it’s a very easy thing to do. There are a lot of resources out there on the web, however, I certainly did not find it straight-forward.

My use case here was very simple: the site had failed to do something, I had the reason, and I just wanted to display that to the user (maybe at some stage I’ll move the response into the body, but I thought this would be an easy option for now.

How

The first step is to bring RouteComponentProps into your React file:

import { RouteComponentProps } from 'react-router';

Your component should have a class signature similar to this:

export class AddSiteFailure extends Component<IProps, IState> {

If you’re interested in some common Typescript syntax differences for React, I recently posted on this very subject.

In the above class definition, we’re accepting IProps and IState. IProps needs to be amended slightly:

interface IProps extends RouteComponentProps<IMatchParams> {    
}

interface IState {
}

So, we’re inheriting from the RouteComponentProps that we imported earlier, and we’re telling it that the structure of the parameters will be defined in an interface called IMatchParams. We’ll need to define that:

interface IMatchParams {
    reason: string
}

Okay, so far, we have a standard props structure, but we’re now inheriting from this new RouteComponentProps, and we’re telling it that the URL parameters will be defined in the interface IMatchParams. So, why does IMatchParams have a string property called “reason”?

The answer to that lies in your App.js / App.tsx. This is the file that manages the routing of your app. In the Render method, your file should have an entry similar to this:

<Route path='/addSiteFailure' component={AddSiteFailure} />

So, you need to tell it that you’ll be accepting a parameter, and you need to give that parameter a name; for example:

<Route path='/addSiteFailure/:reason' component={AddSiteFailure} />

Now, when you navigate to the page, the additional Url parameter will be internally referred to as “reason”, which is how it maps to IMatchParams.reason.

Debugging GitHub Actions

I’ve recently been playing with GitHub actions. Having been around the block a few times, I’ve seen a fair few methods of building and deploying software, and of those, a fair few that are automated in some way. Oddly, debugging these things seems to be in the same place it was around 10 years ago: you see an error, try to work out what caused it, fix it, and run the build / deploy, rinse and repeat.

In some respects, this process may have actually become harder to debug since the days of TFS (at least with TFS, you could connect to the server and see why the software wasn’t building).

Anyway, onto GitHub actions

I’ve been trying to set-up an automated CI/CD pipeline for a new utility that I’ve been playing with.

After I’d configured a basic build, I started getting the following error:

MSBUILD : error MSB1003: Specify a project or solution file. The current working directory does not contain a project or solution file.

So, I thought future me (and perhaps one or two other people) may like to see the process that I went through to resolve (or at least to diagnose) this.

1. Git Bash

Your build is very likely trying to run on a Linux platform. If you have a look at your build file, it will tell you (or, more accurately, you will tell it) where it’s building:

So, the first step is to load up bash and manually type in the commands that the build is executing, one at a time. Again, these are all in the build file:

Make sure that you do this from the root directory, in case your problem relates to the path.

2. Add Debug Steps

Assuming that you’ve done step one and everything is working, the next stage is to start adding some logging. I strongly suspect that someone reading this will tell me there’s an easier way to go about this (please tell me there’s an easier way to go about this!) but this is how I went about adding tracing:

steps:	
	- uses: actions/[email protected]
	- name: Setup .NET Core
	uses: actions/[email protected]
	with:
	dotnet-version: 3.1.101
	- name: where are we
	run: pwd
	- name: list some key files
	run: ls -lrt
	- name: try a different die
	run: ls -lrt websitemeta
	- name: Install dependencies
	run: dotnet restore ./websitemeta/

As you can see, I was working under the assumption that my build was failing because the directory paths were incorrect. In fact, the paths were fine:

With the logging stage, there’s two ways to look at this
1. You’re closely following the scientific method of establishing a hypothesis and testing it; or
2. You’re blindly logging as much information as you can to try and extract a clue.

You’d be surprised how quickly 1 turns into 2!

3. Remember the platform that you’re running on

Okay, so in Step 1, I stated that you should try running the build in bash; but remember that, despite the Unix like interface, you’re still on Windows. As you can see from my build file, my build is on Ubuntu. In my particular case, this held the key – in fact, my build was failing because I’d used the wrong case for the directory path.

This is also true for your tests; for example, if you’ve hard-coded a directory path like this in your test:

string path = "tmp\myfile.txt";

It will fail, because in Unix, it would be:

string path = "tmp/myfile.txt";

Deploying to NuGet Manually and Using GitHub Actions

I’ve been playing with GitHub Actions in order to create some kind of basic pipeline for a little NuGet library that I created. In this post, I’ll describe the manual process, and then one option for automating that process.

Manual process

The manual process is actually not too bad. I know that CI/CD is the latest TDD (that is, the thing that everyone wants to agree is a good thing); and I’m not saying it’s a bad thing – I am, however, saying that if you have a limited amount of time, and no product to deploy, your time may be better spent creating one, rather than creating a deployment pipeline for something that doesn’t exist. Having a deployment process that’s written down in a text file has its downsides, but people will first judge your software by it’s quality, not by the method it arrived on the server.

Having said that, one thing that automating this whole process does give you, is a guarantee that all the tests are passing before it gets published.

The first step in deploying a NuGet package is to configure the properties of the project. You can have VS generate the NuGet package for you (Generate NuGet package on build), or you can do so yourself. Either way, you’ll need to update the version number:

Assuming that you didn’t ask VS to generate on build, your next step is to switch to the Release profile, build and the “Pack” the project:

Pack will produce a .nupkg file, which you’ll find in your bin folder:

This assumes that you’ve previously created the NuGet package in NuGet; if you have then log-in to nuget.org and select to upload a new package:

Point it to your lastest.nupkg, and the package is published.

That whole process takes around 2 – 3 minutes, maybe less.

GitHub Actions

So, we’ve got a relatively smooth manual deployment pipeline, and I had a bit of a diatribe at the start of this post about how great manual deployments are. You may be wondering why I’m trying to automate this. In fact, there are two big advantages to an automated deployment (apart from the fact that I just wanted to play with GitHub actions!):

1. You’re guaranteed to have your tests pass before deployment.
2. There’s a record of the deployment, and what was deployed.

Specifically, GitHub actions has the following advantages over most other deployment pipelines:

1. It’s free.

Setting up a New Pipeline

To start with, navigate to the Actions tab under your repository in GitHub:

Here, you’re presented with a list of pre-built workflows – some relate more to what you may be doing than others. Basically, GitHub uses a language analyser to try and work out what language you’re using for your project and gives you options based on that.

The default workflow does a build, and then runs the tests, so let’s set that one up first:

You’re then taken to a YAML editor (unfortunately, YAML seems to be the language of choice for GitHub Actions):

Let’s make a mental note of the “marketplace” on the right hand side, but for now, let’s just save this, and see what happens.

We can now test this by navigating to Actions, and generating a push:

If your build fails (like mine) you can have a look in the logs:

You can drill into each section, and see the error; for example:

To fix the issues, you can edit the build directly in GitHub, and then re-try the build. I’m planning a follow-up post to this on some techniques for debugging these things.

Once that’s working, we want to publish to NuGet. Let’s have a look if there’s anything already out there:

The Marketplace has hundreds of pre-built worfklows that you can just incorporate into your own. Simply copy the supplied YAML. For my project, it looks like this:

name: .NET Core	
	on:
	push:
	branches: [ master ]
	pull_request:
	branches: [ master ]
	jobs:
	build:
	runs-on: ubuntu-latest
	steps:
	- uses: actions/[email protected]
	- name: Setup .NET Core
	uses: actions/[email protected]
	with:
	dotnet-version: 3.1.101
	- name: Install dependencies
	run: dotnet restore ./WebSiteMeta/
	- name: Build
	run: dotnet build --configuration Release --no-restore ./WebSiteMeta
	- name: Test
	run: dotnet test --no-restore --verbosity normal ./WebSiteMeta
	- name: Publish NuGet
	uses: rohith/[email protected]
	with:
	# Filepath of the project to be packaged, relative to root of repository
	PROJECT_FILE_PATH: WebSiteMeta/WebSiteMeta.Scraper/WebSiteMeta.Scraper.csproj
	# NuGet package id to check against version changes, defaults to project name
	#PACKAGE_NAME: # optional
	# Filepath containing version info, relative to root of repository
	#VERSION_FILE_PATH: # optional
	# Regex pattern to extract version info in a capturing group
	#VERSION_REGEX: # optional, default is <Version>(.*)<\/Version>
	# Static version, useful for external providers like Nerdbank.GitVersioning
	#VERSION_STATIC: # optional
	# Flag to enable / disable git tagging
	TAG_COMMIT: false # optional, default is true
	# Format of the git tag, `[*]` gets replaced with version
	#TAG_FORMAT: # optional, default is v*
	# API key for the NuGet feed
	NUGET_KEY: ${{secrets.NUGET_API_KEY}} # optional

If you’re interested how the secret was generated, then have a look at this earlier post.