Monthly Archives: June 2018

Separating Data Access in Asp.Net Core 2

In Asp.Net Core 2, like in previous incarnations of Asp.Net there is a wizard that gives you a head-start with a a simple user log-in / registration system:

If you set-up a new project using the wizard to create an individual user account, you may notice in the generated project, the lack of seemingly any code to achieve this. The reason being that all the code for the identity system is tucked away inside the razor pages. I see this as mainly a good thing, but with one exception*: I don’t like having the DB access code inside the main web project; it makes DI very difficult. So this is the story of how you can extricate the DB Access portion of this into a separate project.

Context

The crux of this is to move the context into a separate project; so let’s start with a new project:

If you just want the identity access, then you’ll only need to move the
ApplicationIdentityDbContext, however, in real life, you’re probably going to end up with two contexts:

The contexts themselves need to be separate because the identity context inherits from IdentityDbContext**:

public class ApplicationIdentityDbContext : IdentityDbContext
{
    
    public ApplicationIdentityDbContext(DbContextOptions<ApplicationIdentityDbContext> options)
        : base(options)
    {
    }
}

Your second context should just inherit from DbContext.

NuGet

There’s a couple of gotcha’s with this; but the libraries that you need in the DataAccess project are:

Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.Entensions.Identity.Stores

Startup.cs

Finally, you’ll need to change the DI to register both contexts:

services.Configure<IdentityOptions>(options =>
{
    options.Password.RequireNonAlphanumeric = false;                
});
services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<ApplicationIdentityDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));
 
services                
    .AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationIdentityDbContext>();

I’m using SqlServer here, so if you’re not then you’ll obviously need to change the bits around that. You’ll notice that I switched the requirement to have your password have a non-alphanumeric character – especially for development, this can be annoying. I also don’t necessarily accept that it increases security for the site***.

Migrations

Now that you have multiple contexts, when you add a migration, you’ll need to specify the context to use; for example:

Add-Migration "InitialUserSetup" -context ApplicationIdentityDbContext

The same is true for Update-Database:

Update-Database -context ApplicationIdentityDbContext

Footnotes

* Okay – there may be other pitfalls; but if this works for 60% of the authentication cases, why not have it all inside a magic black box? When you need something more customised, you can always rip this out and replace it with your own.

** There’s nothing stopping you having the main DbContext inherit from IdentityDbContext, or just using IdentityDbContext as the main context.

*** Obviously, it does improve security for the site if everyone is using a 20 digit code and they start using non-alpha-numeric characters in that code; however, if they’re using a password manager, they probably are already generating such a code, and if not then you’ll just force “Password123” to “!Password123”, so you probably don’t gain much!

References

https://github.com/aspnet/EntityFrameworkCore/issues/7891

An excellent intro to Asp.Net Core 2 default structure

Asp.Net Core 2.0 – Passing data into a Model Using DI

Imagine you have an Asp.Net Core web page, and you would like to edit some data in a form, but you’d like to default that data to something (maybe initially specified in the Web.Config).

I’m sure there’s dozens of ways to achieve this; but this is one.

Let’s start with a bog standard MVC web app:

Step one is to define a model in which to hold your data; here’s mine:

public class CurrentAppData
{
    public string DataField1 { get; set; }
}

Let’s register that in the IoC container:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });
 
 
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
 
    services.AddTransient<CurrentAppData, CurrentAppData>(
        a => new CurrentAppData()
        {
            DataField1 = "test value"
        });

Next thing we’ll need is a View, and a corresponding view model to edit our data; here’s the view:

@model EditDataViewModel
@{
    ViewData["Title"] = "Edit Data";
}
 
<h2>@ViewData["Title"]</h2>
 
<div>
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
 
</div>

And now the view model (that is, the model that is bound to the view):

public class EditDataViewModel
{
    public EditDataViewModel(CurrentAppData editData)
    {
        EditData = editData;
    }
    public CurrentAppData EditData { get; set; }
}

The final step here is to adapt the controller so that the CurrentAppData object is passed through the controller:

public class EditDataController : Controller
{
    private readonly CurrentAppData _currentAppData;
 
    public EditDataController(CurrentAppData currentAppData)
    {
        _currentAppData = currentAppData;
    }
 
    public IActionResult EditData()
    {
        return View(new EditDataViewModel(_currentAppData));
 
 
    }
}

That works as far as it goes, and we now have the data displayed on the screen:

The next step is to post the edited data back to the controller; let’s change the HTML slightly:

<form asp-action="UpdateData" asp-controller="EditData" method="post" enctype="multipart/form-data">
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
    <br />
    <button type="submit" class="btn-default">Submit Changes</button>
</form>

We’ve added a submit button, which should cause the surrounding form element to execute whichever “method” it’s been told to (in this case, POST). It will look for an action on the controller called UpdateData, so we should create one:

public IActionResult UpdateData(EditDataViewModel editDataViewModel)
{
    System.Diagnostics.Debug.WriteLine(editDataViewModel.EditData.DataField1);
    return View("EditData", editDataViewModel);
}

Here, we’re accepting the EditDataViewModel from the view. However; when we run this, we get the following error:

Error:

InvalidOperationException: Could not create an instance of type ‘WebApplication14.Models.EditDataViewModel’. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the ‘editDataViewModel’ parameter a non-null default value.

Let’s first implement a fix for this, and then go into the whys and wherefores. The fix is actually quite straightforward; simply give the view model a parameterless constructor:

public class EditDataViewModel
{
    public EditDataViewModel()
    {
        
    }
 
    public EditDataViewModel(CurrentAppData editData)
    {
        EditData = editData;
    }
    public CurrentAppData EditData { get; set; }
}

The problem that we had here is that the `EditDataViewModel` that is returned to UpdateData is a new instance of the model. We can prove this by changing our code slightly:

Here, we’ve added a field called TestField1 to the model, and populated it just before we pass the model to the view; and on the post back, it’s gone. I’m not completely sure why the view model can’t be created by the middleware in the same way that the controller is; but that’s the subject of another post.

Finally, show the value back to the screen

To wrap up, we’ll just show the same value back to the screen; we’ll add an extra value to the model:

public class CurrentAppData
{
    public string DataField1 { get; set; }
 
    public string DisplayField1 { get; set; }
}

And we’ll just display it in the view:

<form asp-action="UpdateData" asp-controller="EditData" method="post" enctype="multipart/form-data">
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
    <br />
    <button type="submit" class="btn-default">Submit Changes</button>
    <br />
    <label>@Model.EditData.DisplayField1</label>
    <br />
</form>

Finally, we’ll copy that value inside the controller (obviously, this is simulating something meaningful happening), and then display the result:

public IActionResult UpdateData(EditDataViewModel editDataViewModel)
{
    editDataViewModel.EditData.DisplayField1 = editDataViewModel.EditData.DataField1;
    return View("EditData", editDataViewModel);
}

Let’s see what that looks like:

Using Event Hubs to Create a Multi-player Game

In this previous post, I introduced Azure Event Hubs (to myself mostly). In this post, I’m going to attempt to create a very basic multi-player game, using Event Hubs to manage the multi-player part.

I’ve previously written extensively on MonoGame, although I haven’t done anything with it for a while.

Getting started with MonoGame

The first step is to install the MonoGame framework from here. At the time of writing, 3.6 was the latest version. This was released over a year ago, so maybe that says something about the direction this game platform is going. I’ve heard a lot of rumours about Microsoft buying Unity (which I believe is ultimately based on MonoGame) so it’s odd that they wouldn’t want to take this over (especially given that it’s a fork of XNA).

Once you’ve installed MonoGame, in VS create a new project; you’ll be beset by MonoGame project types:

For now, we’ll create a Windows MonoGame Project. For the purpose of this example, you’ll need to install the MonoGame.Extended NuGet package.

Let’s start off with a really simple game – this basically gives you a red dot on the screen, and you can move it around:

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Vector2 _playerPosition;
    Random _random = new Random();
    private float _momentumUp = 0;
    private float _momentumRight = 0;
 
    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }
 
    protected override void Initialize()
    {
        _playerPosition = GetRandomVector();
        base.Initialize();
    }
 
    private Vector2 GetRandomVector()
    {
        Vector2 vector2 = new Vector2(_random.Next(GraphicsDevice.Viewport.Width), _random.Next(GraphicsDevice.Viewport.Height));
        return vector2;
    }
 
    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
    }
 
    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();
 
        if (Keyboard.GetState().IsKeyDown(Keys.A) || Keyboard.GetState().IsKeyDown(Keys.Left))
            _momentumRight -= 0.1f;
        else if (Keyboard.GetState().IsKeyDown(Keys.D) || Keyboard.GetState().IsKeyDown(Keys.Right))
            _momentumRight += 0.1f;
        else if (Keyboard.GetState().IsKeyDown(Keys.W) || Keyboard.GetState().IsKeyDown(Keys.Up))
            _momentumUp -= 0.1f;
        else if (Keyboard.GetState().IsKeyDown(Keys.X) || Keyboard.GetState().IsKeyDown(Keys.Down))
            _momentumUp += 0.1f;
 
        _playerPosition.X += (float)_momentumRight;
        _playerPosition.Y += (float)_momentumUp;
 
        base.Update(gameTime);
    }
 
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
 
        spriteBatch.Begin();            
        spriteBatch.DrawCircle(_playerPosition, 10f, 30, new Color(255, 0, 0), 10);
        spriteBatch.End();
 
        base.Draw(gameTime);
    }
 
}

As you can see from the above code, we’re just moving a ball around the screen. If you installed this on a second machine, they would also be able to move that ball as well; at this stage, neither screen would be aware in any sense of the other screen. The next step is that we want to see the ball from the first screen on the second. We won’t mess about with collision, as this isn’t about the game, it’s about the Event Hub traffic.

The EventHub client library in the post mentioned above is for .Net Standard only, so we’ll need to use the Service Bus Client Library.

The basis of what we’ll do next is to simply take the current player position and send it to Event Hub; however, to cater for the fact that more than one player will have a position, we’ll need to identify it. Let’s start by creating a class to encompass this information:

public class PlayerData
{
    public float PlayerPositionX { get; set; }
    public float PlayerPositionY { get; set; }
 
    public Vector2 GetPlayerPosition()
    {
        return new Vector2(PlayerPositionX, PlayerPositionY);
    }
    public Guid PlayerId { get; set; } = Guid.NewGuid();
}

I’ve taken this opportunity to replace the Vector2, which is a struct, with class members. Changing the data in structs can end up with strange behaviour… and in this particular case, it point blank refuses to let you, but gives a message that says it can’t recognise the variable.

Now we’ll need to re-jig the calling code a little to reference this new class instead of the player position:

protected override void Initialize()
{
    _playerData = new PlayerData()
    {
        PlayerPositionX = _random.Next(GraphicsDevice.Viewport.Width),
        PlayerPositionY = _random.Next(GraphicsDevice.Viewport.Height)
    };
    base.Initialize();

EventHub

Let’s add the event hub code here. In this article, I discussed how you might deal with a situation where you’re trying to send non-critical data in rapid succession, using a locking mechanism. Let’s start by writing the code to send the message:

private static object _lock = new object();
private async Task SendPlayerInformation()
{
    if (Monitor.TryEnter(_lock))
    {
        string data = JsonConvert.SerializeObject(_playerData);
        await _eventHubSender.SendData(data);
    }
}

This will need to be called inside the Update method:

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();
 
    if (Keyboard.GetState().IsKeyDown(Keys.A) || Keyboard.GetState().IsKeyDown(Keys.Left))
        _momentumRight -= 0.1f;
    else if (Keyboard.GetState().IsKeyDown(Keys.D) || Keyboard.GetState().IsKeyDown(Keys.Right))
        _momentumRight += 0.1f;
    else if (Keyboard.GetState().IsKeyDown(Keys.W) || Keyboard.GetState().IsKeyDown(Keys.Up))
        _momentumUp -= 0.1f;
    else if (Keyboard.GetState().IsKeyDown(Keys.X) || Keyboard.GetState().IsKeyDown(Keys.Down))
        _momentumUp += 0.1f;
 
    if (_momentumRight != 0 || _momentumUp != 0)
    {
        _playerData.PlayerPositionX += (float)_momentumRight;
        _playerData.PlayerPositionY += (float)_momentumUp;
        SendPlayerInformation(); // Do not wait for this to finish
    }
 
    base.Update(gameTime);
}

SendPlayerInformation is a fire and forget method. Generally, using await statements inside MonoGame can cause some very strange, and difficult to diagnose issues. The reason being that the premise of a game loop is that it executes repeatedly – that’s how the game keeps updating: the Update method allows you to rapidly change the state of the game, and the Draw method allows that state to be rendered to the screen. However, if you stick an await in there, you’ve returned control to the caller, and because none of the MonoGame stack works with the async / await paradigm, the result is that the entire loop waits for your task. In the Draw method, this will result in an obvious blip in the rendering; but in the Update method, the effect will be more subtle.

Other Players

The next step is to implement the listener. Again, this is slightly different when using the service bus libraries:

public class EventHubListener : IEventProcessor
{
 
    public async Task Start(Guid hostId)
    {
        _eventHubClient = EventHubClient.CreateFromConnectionString(EhConnectionString);
        EventHubConsumerGroup defaultConsumerGroup = _eventHubClient.GetDefaultConsumerGroup();            
        EventHubDescription eventHub = NamespaceManager.CreateFromConnectionString(EhConnectionStringNoPath).GetEventHub(EhEntityPath);
 
        foreach (string partitionId in eventHub.PartitionIds)
        {
            defaultConsumerGroup.RegisterProcessor<EventHubListener>(new Lease
            {
                PartitionId = partitionId
            }, new EventProcessorCheckpointManager());
 
            Console.WriteLine("Processing : " + partitionId);
        }
        
    }
 
    public Task OpenAsync(PartitionContext context)
    {
        return Task.FromResult<object>(null);
    }
 
    public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
    {
        if (_startDate == null)
            _startDate = DateTime.UtcNow;
 
        System.Diagnostics.Debug.WriteLine("ProcessEventsAsync Start");
        System.Diagnostics.Debug.WriteLine(context.Lease.PartitionId);
 
        var filteredMessages =
            messages.Where(a => a.EnqueuedTimeUtc >= _startDate)
            .OrderBy(a => a.EnqueuedTimeUtc);
        foreach (EventData eventData in filteredMessages)
        {
            
            System.Diagnostics.Debug.WriteLine(context.ConsumerGroupName);
            System.Diagnostics.Debug.WriteLine(eventData.PartitionKey);                                
 
            string bytes = Encoding.UTF8.GetString(eventData.GetBytes());
            PlayerData data = JsonConvert.DeserializeObject<PlayerData>(bytes);

            // If we're processing this player then stop
            if (Game1.ThisPlayerGuid == data.PlayerId)
            {
                _eventHubClient = EventHubClient.CreateFromConnectionString(EhConnectionString);
                EventHubConsumerGroup defaultConsumerGroup = _eventHubClient.GetDefaultConsumerGroup();
 
                defaultConsumerGroup.UnregisterProcessor(context.Lease, CloseReason.Shutdown);
                System.Diagnostics.Debug.WriteLine("Unregistering listener...");
                return;
            }
 
            if (Game1.AllPlayerData.ContainsKey(data.PlayerId))
            {
                System.Diagnostics.Debug.WriteLine(data.PlayerId);
 
                var playerData = Game1.AllPlayerData[data.PlayerId];
                playerData.PlayerPositionX = data.PlayerPositionX;
                playerData.PlayerPositionY = data.PlayerPositionY;
            }
            else
            {
                Game1.AllPlayerData.Add(data.PlayerId, data);
            } 
        }
 
        await context.CheckpointAsync();
        System.Diagnostics.Debug.WriteLine("ProcessEventsAsync End");
    }

As you can see, there’s a bit of faffing to get this going. The code does seem a little convoluted, but essentially all we’re doing is finding any messages that were queued after we started processing (this is a very crude checkpoint), and then look for that Player Id; if we find it then we move it, and if we don’t then we create it. There’s also a little check in there to make sure we’re not processing echos!

As it stands, this only registers the clients on start-up, meaning that, whilst client 2 can see client 1, client 1 cannot see client 2.

As you can see, the player on instance one is replicated on instance two. Remember that it only starts broadcasting after movement, so the player will need to move to appear in the second instance.

In the next post, I’ll investigate the possibility of using a game controller to allow both clients to interact simultaneously (or at least be simultaneously visible).

References

https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-dotnet-framework-getstarted-send

http://www.bloggedbychris.com/2014/08/16/exploring-azure-event-hubs-code-implementation/

https://alexandrebrisebois.wordpress.com/2014/07/18/getting-acquainted-with-azure-service-bus-event-hubs/

https://mikhail.io/2017/05/reliable-consumer-of-azure-event-hubs/

Short Walks – Object Locking in C#

While playing with Azure Event Hubs, I decided that I wanted to implement a thread locking mechanism that didn’t queue. That is, I want to try and get a lock on the resource, and if it’s currently in use, just forget it and move on. The default behaviour in C# is to wait for the resource. For example, consider my method:

static async Task MyProcedure()
{
    Console.WriteLine($"Test1 {DateTime.Now}");
    await Task.Delay(5000);
    Console.WriteLine($"Test2 {DateTime.Now}");
}

I could execute this 5 times like so:

static async Task Main(string[] args)
{
    Parallel.For(1, 5, (a) =>
    {
        MyProcedure();
    });
 
    Console.ReadLine();
}

If I wanted to lock this (just bear with me and assume that makes sense for a minute), I might do this:

private static object _lock = new object();        
 
static async Task Main(string[] args)
{
    Parallel.For(1, 5, (a) =>
    {
        //MyProcedure();
        Lock();
    });
 
    Console.ReadLine();
}
 
static void Lock()
{
    Task.Run(() =>
    {
        lock (_lock)
        {
            MyProcedure().GetAwaiter().GetResult();
        }
    });
}

I re-jigged the code a bit, because you can’t await inside a lock statement, and obviously, just making the method call synchronous would not be locking the asynchronous call.

So now, I’ve successfully made my asynchronous method synchronous. Each execution of `MyProcedure` will happen sequentially, and that’s because `lock` queues the locking calls behind one another.

However, imagine the Event Hub scenario that’s referenced in the post above. I have, for example, a game, and it’s sending a large volume of telemetry up to the cloud. In my particular case, I’m sending a player’s current position. If I have a locking mechanism whereby the locks are queued then I could potentially get behind; and if that happens then, at best, the data sent to the cloud will be outdated and, at worse, it will use up game resources, potentially causing a lag.

After a bit of research, I found an alterntive:

private static object _lock = new object();        
 
static async Task Main(string[] args)
{
    Parallel.For(1, 5, (a) =>
    {
        //MyProcedure();
        //Lock();
        TestTryEnter();
    });
 
    Console.ReadLine();
}

static async Task TestTryEnter()
{
    bool lockTaken = false;
 
    try
    {
        Monitor.TryEnter(_lock, 0, ref lockTaken);
 
        if (lockTaken)
        {
            await MyProcedure();                                        
        }
        else
        {
            Console.WriteLine("Could not get lock");
        }
    }
    finally
    {
        if (lockTaken)
        {
            Monitor.Exit(_lock);
        }
    }
}

So here, I try to get the lock, and if the resource is already locked, I simply give up and go home. There are obviously a very limited number of uses for this; however, my Event Hub scenario, described above, is one of them. Depending on the type of data that you’re transmitting, it may make much more sense to have a go, and if you’re in the middle of another call, simply abandon the current one.