Tag Archives: c#

Manually Creating a Test Harness in .Net

Let me start by saying that this post isn’t intended to try to replace Selenium, or Cypress, or whatever UI testing tools you may choose to use. In fact, it’s something that I did for manual testing, although it’s not difficult to imagine introducing some minor automation.

The Problem

Imagine that you have a solution that requires some data – perhaps it requires a lot of data, because you’re testing some specific performance issue, or perhaps you just want to see what the screen looks like when you have a lot of data. Let’s also imagine that you’re repeatedly running your project for one reason or another, and adding data, or whatever.

My idea here was that I could create a C# application that scripts this process, but because it’s an internal application, I could give it access to the data layer directly.

The Solution

Basically, the solution to this (and to many things) was a console app. Let’s take a solution that implements a very basic service / repository pattern:

From this, we can see that we have a pretty standard layout, and essentially, what we’re trying to do is insert some data into the database. It’s a bonus if we can add some test coverage while we’re at it (manual test coverage is still test coverage – it just doesn’t show up on your stats). So, if you’re using a REST type pattern, you might want to use the controller endpoints to add the data; but for my purpose, I’m just going to add the data directly into the data access layer.

Let’s see what the console app looks like:

        static async Task Main(string[] args)
        {
            IConfiguration configuration = new ConfigurationBuilder()
                  .AddJsonFile("appsettings.json", true, true)
                  .Build();

            // Ensure the DB is populated
            var dataAccess = new TestDataAccess(configuration.GetConnectionString("ConnectionString"));
            if (dataAccess.GetDataCount() == 0)
            {
                var data = new List<MyData>();

	     // Generate 100 items of data
                for (int j = 0; j <= 100; j++)
                {
		var dataItem = CreateTestItem();
                      data.Add(dataItem);
                }
                dataAccess.AddDataRange(data);
            }

            // Launch the site            
            await RunCommand("dotnet", "build");
            await RunCommand("dotnet", "run", 5);

            System.Diagnostics.Process.Start(@"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", @"https://localhost:5001");
        }

Okay, so let’s break this down: there’s essentially three sections to this: configuration, adding the data, and running the app.

Configuration

We’ll start with the configuration:

       IConfiguration configuration = new ConfigurationBuilder()
                  .AddJsonFile("appsettings.json", true, true)
                  .Build();

        // Ensure the DB is populated
        var dataAccess = new TestDataAccess(configuration.GetConnectionString("ConnectionString"));

Because we’re using a console app, we’ll need to get the configuration; you could copy the appsettings.json, but my suggestion would be to add a link; that is, add an existing item, and select that item from the main project, then choose to “Add As Link” (this is not a new feature):

This means that you’ll be able to change the config file, and it will be reflected in the test harness.

Creating the data

There’s not too much point in me covering what’s behind TestDataAccess – suffice to say that it encapsulates the data access layer; which, as a minimum, requires the connection string.

It’s also worth pointing out that we check whether there is any data there before running it. Depending on your specific use-case, you may choose to remove this.

Building, running, and launching the app

Okay, so we’ve now added our data, we now want to build the main application – thanks to the command line capabilities of .Net Core, this is much simpler than it was when we used to have to try and wrangle with MSBuild!

    // Launch the site            
    await RunCommand("dotnet", "build");
    await RunCommand("dotnet", "run", 5);

    await RunCommand(@"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", @"https://localhost:5001");

RunCommand probably needs a little more attention, but before we look at that, let’s think about what we’re trying to do:

1. Build the application
2. When the application has built, run the application
3. Once the application is running, navigate to the site

RunCommand looks like this:

        private static async Task RunCommand(string command, string? args = null, int? waitSecs = -1)
        {
            Console.WriteLine($"Executing command: {command} (args: {args})");

            Process proc = new System.Diagnostics.Process();
            proc.StartInfo.WorkingDirectory = @"..\..\..\..\MyApp.App";
            proc.StartInfo.FileName = command;
            proc.StartInfo.Arguments = args ?? string.Empty;

            proc.Start();

            if ((waitSecs ?? -1) == -1)
            {
                proc.WaitForExit();
            }
            else
            {
                if (waitSecs! == 0) return;
                await Task.Delay(waitSecs!.Value * 1000);
            }
        }

“But this looks inordinately complicated for a simple wrapper for running a process!” I hear you say.

It is a bit, but the essence is this: when running the build command, we need to wait for it to complete, when running the run command, we can’t wait for it to complete, because it never will; but we do need to move to the next thing; and when we launch the site, we don’t really care whether it waits or not after that.

Summary

I appreciate that some of you may be regretting spending the time reading through this, as all I’ve essentially done is script some data creation and run an application; but I imagine there are some people out there, like me, that want to see (visually) what their app looks like with different data shapes.

Using HttpClientFactory

In .Net Framework (prior to .Net Core), HttpClient was something of a pain. You essentially kept it around in a static variable. If you didn’t, and used too many of them, you could end up issues such as socket exhaustion.

I think most people got around this by implementing their own version of a HttpClientFactory… but now you don’t need to.

In this post, I’m covering the simplest possible use case inside an Asp.Net Core application. The articles linked at the bottom of this post go into much more detail.

Usage

The first step to using the HttpClientFactory is to add it to the IoC:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddHttpClient();
        }

Then, simply inject it into your controller; for example:

        public HomeController(ILogger<HomeController> logger,
            IHttpClientFactory clientFactory)
        {
            _logger = logger;
            _clientFactory = clientFactory;
        }

Finally, you request a client like this:

var client = _clientFactory.CreateClient();

Then you can use it as a normal HttpClient:

var result = await client.GetAsync($"https://localhost:22222/endpoint");

References

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1

https://www.stevejgordon.co.uk/introduction-to-httpclientfactory-aspnetcore

Calling an Azure Signalr Instance from an Azure function

I’ve been playing around with the Azure Signalr Service. I’m particularly interested in how you can bind to this from an Azure function. Imagine the following scenario:

You’re sat there on your web application, and I press a button on my console application and you suddenly get notified. It’s actually remarkably easy to set-up (although there are definitely a few little things that can trip you up – many thanks to Anthony Chu for his help with some of those!)

If you want to see the code for this, it’s here.

Create an Azure Signalr Service

Let’s start by setting up an Azure Signalr service:

You’ll need to configure a few things:

The pricing tier is your call, but obviously, free is less money than … well, not free! The region should be wherever you plan to deploy your function / app service to, although I won’t actually deploy either of those in this post, and the ServiceMode should be Serverless.

Once you’ve created that, make a note of the connection string (accessed from Keys).

Create a Web App

Follow this post to create a basic web application. You’ll need to change the startup.cs as follows:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR().AddAzureSignalR();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //app.UseDefaultFiles();
            //app.UseStaticFiles();

            app.UseFileServer();
            app.UseRouting();
            app.UseAuthorization();

            app.UseEndpoints(routes =>
            {
                routes.MapHub<InfoRelay>("/InfoRelay");
            });
        }

Next, we’ll need to change index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    
    <script src="lib/@microsoft/signalr/dist/browser/signalr.js"></script>
    <script src="getmessages.js" type="text/javascript"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">

</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-2">
                <h1><span class="label label-default">Message</span></h1>
            </div>
            <div class="col-4">
                <h1><span id="messageInput" class="label label-default"></span></h1>
            </div>
        </div>
        <div class="row">&nbsp;</div>
    </div>
    <div class="row">
        <div class="col-12">
            <hr />
        </div>
    </div>
</body>

</html>

The signalr package that’s referenced is an npm package:

npm install @microsoft/signalr

Next, we need the getmessages.js:

function bindConnectionMessage(connection) {
    var messageCallback = function (name, message) {
        if (!message) return;

        console.log("message received:" + message.Value);

        const msg = document.getElementById("messageInput");
        msg.textContent = message.Value;
    };
    // Create a function that the hub can call to broadcast messages.
    connection.on('broadcastMessage', messageCallback);
    connection.on('echo', messageCallback);
    connection.on('receive', messageCallback);
}

function onConnected(connection) {
    console.log("onConnected called");
}

var connection = new signalR.HubConnectionBuilder()
    .withUrl('/InfoRelay')
    .withAutomaticReconnect()
    .configureLogging(signalR.LogLevel.Debug)
    .build();

bindConnectionMessage(connection);
connection.start()
    .then(function () {
        onConnected(connection);
    })
    .catch(function (error) {
        console.error(error.message);
    });

The automatic reconnect and logging are optional (although at least while you’re writing this, I would strongly recommend the logging).

Functions App

Oddly, this is the simplest of all:

    public static class Function1
    {       
        [FunctionName("messages")]
        public static Task SendMessage(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] object message,
            [SignalR(HubName = "InfoRelay")] IAsyncCollector<SignalRMessage> signalRMessages)
        {
            return signalRMessages.AddAsync(
                new SignalRMessage
                {
                    Target = "broadcastMessage",
                    Arguments = new[] { "test", message }
                });
        }
    }

The big thing here is the binding – SignalRMessage binding allows it to return the message to the hub (specified in HubName). Also, pay attention to the Target – this needs to match up the the event that the JS code is listening for (in this case: “broadcastMessage”).

Console App

Finally, we can send the initial message to set the whole chain off – the console app code looks like this:

        static async Task Main(string[] args)
        {
            Console.WriteLine($"Press any key to send a message");
            Console.ReadLine();

            HttpClient client = new HttpClient();
            string url = "http://localhost:7071/api/messages";
            
            HttpContent content = new StringContent("{'Value': 'Hello'}", Encoding.UTF8, "application/json");

            HttpResponseMessage response = await client.PostAsync(url, content);
            string results = await response.Content.ReadAsStringAsync();

            Console.WriteLine($"results: {results}");
            Console.ReadLine();
        }

So, all we’re doing here is invoking the function.

Now when you run this (remember that you’ll need to run all three projects), press enter in the console app, and you should see the “Hello” message pop up on the web app.

References

https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-3.1

https://docs.microsoft.com/en-us/aspnet/core/signalr/dotnet-client?view=aspnetcore-3.1&tabs=visual-studio

https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-signalr-service?tabs=csharp

Policy Server with Asp.Net Core

It took me a while to collate my notes for this; hopefully this will be the first in a vaguely related series on using Policy Server.

Policy Server is a product from a company called Solliance, allowing you to control authorisation within your application (as opposed to authentication – the same company produces a sister product, called Identity Server). The idea is that, the user is authenticated to determine they are who they say they are, but then authorised to use certain parts of the application, or to do certain things.

This post discusses setting up the open source version of Policy Server. There is a commercial version of this.

The ReadMe on the above GitHub page is quite extensive, however, when I was trying this out, I had some areas that I thought weren’t too clear. This post will explain that to me in the future, should I become unclear again (a common occurrence when you get to a certain age!)

It’s worth bearing in mind that authorisation and authentication need to be done on the server; whilst you may choose to also do that on the client, the code on the client is, well, on the client! If you have some Javascript code sat in the web browser that’s stopping me from seeing the defence plans, then that’s just not secure enough.

Installing and Configuring Policy Server

The first step here is to install the NuGet package:

Install-Package PolicyServer.Local

Next, add Policy Server in startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            // In production, the React files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/build";
            });

            services.AddPolicyServerClient(Configuration.GetSection("Policy"));
    }

Amazingly, at this stage, you’re basically done. The next stage is to add the rules into the appsettings.json. There is an example on the page above, but here’s a much simpler one:

  "Policy": {
    "roles": [
      {
        "name": "salesmanager",
        "subjects": [ "1" ]
      },
      {
        "name": "driver",
        "subjects": [ "2" ]
      }
    ],
    "permissions": [
      {
        "name": "ViewRoutes",
        "roles": [ "driver" ]
      },
      {
        "name": "CreateSalesOrder",
        "roles": [ "salesmanager" ]
      },
      {
        "name": "Timesheet",
        "roles": [ "salesmanager", "driver" ]
      }
    ]
  }

This is, in fact, the part that I didn’t feel was clear enough in the GitHub readme. What, exactly, are “subjects”, and how do I associate them to anything useful? I’ll come back to this shortly, but first, let’s see the rules that we have set up here:

The Sales Manager can create a sales order, and complete their timesheet.

The Driver can view routes and complete their timesheet.

The Sales Manager can not view routes; nor can the driver create a sales order.

Add Policy Server to a Controller

The next stage is to inject Policy Server into our controller. For the home controller, all you need to do is inject IPolicyServerRuntimeClient:

        private readonly IPolicyServerRuntimeClient _policyServerRuntimeClient;

        public HomeController(IPolicyServerRuntimeClient policyServerRuntimeClient)
        {
            _policyServerRuntimeClient = policyServerRuntimeClient;
        }

This can now be used anywhere in the controller. However, for testing purposes, let’s just circle back round to the subject question. The subject is the identity of the user. You may have noticed that I’ve started this post with PolicyServer, so I don’t have any authentication in place here. However, for testing purposes, we can force our user to a specific identity.

Let’s override the Index method of the HomeController:

        public async Task<IActionResult> Index()
        {
            var identity = new ClaimsIdentity(new Claim[]
            {
                new Claim("sub", "2"),
                new Claim("name", "TestUser")
            }, "test");

            User.AddIdentity(identity);

            var homeViewModel = await SecureViewModel();
            return View(homeViewModel);
        }

We’ll come back to the ViewModel business shortly, but let’s focus on the new ClaimsIdentity; notice that the “sub” (or subject) refers to the Subject ID of the driver above. So what we’ve done is created a driver!

The SecureViewModel method returns a ViewModel (which, as you can see, is passed to the view); let’s see what that might look like:

        public async Task<HomeViewModel> SecureViewModel()
        {
            var homeViewModel = new HomeViewModel();            
            homeViewModel.ViewRoutes = await _policyServerRuntimeClient.HasPermissionAsync(User, "ViewRoutes");
            homeViewModel.CreateSalesOrder = await _policyServerRuntimeClient.HasPermissionAsync(User, "CreateSalesOrder");
            homeViewModel.Timesheet = await _policyServerRuntimeClient.HasPermissionAsync(User, "Timesheet");

            return homeViewModel;
        }

You can play about with how this works by altering the “sub” claim.

How does this fit into Identity Server (or an identity server such as Azure B2C)?

The identity result of the authentication, should map to the “sub” claim. In some cases, it’s “nameidentitifier”. Once you’ve captured that, you’ll need to store that reference against the user record.

That’s all very well for testing, but when I use this for real, I want to plug my data in from a database

The first thing you’ll need to do is to ‘flatten’ the data. this StackOverflow question was about the best resource I could find for this, and it gets you about 90% of the way there. I hope to come back to that, and linking this in with Asp.Net Core Policies in the next post.

References

https://auth0.com/blog/role-based-access-control-rbac-and-react-apps/

https://github.com/IdentityServer/IdentityServer4/issues/2968

https://stackoverflow.com/questions/55450393/persist-entitys-in-database-instead-of-appsettings-json

https://stackoverflow.com/questions/55450393/persist-entitys-in-database-instead-of-appsettings-json

Simple binding in Blazor

A while back, I asked on Dev about moving my blog from WordPress to … well, not WordPress anymore. My main critera was to Markdown instead of whatever the WordPress format is called. The main issue being that you need to replace the code tags.

I resolved to create a tool to do it for me. I’m doing so in Blazor.

The first task was to create a very simple data binding scenario, so I could handle all the view logic in the View Model. I’ve previously written about using view models. This post covers the scenario where you want to bind text boxes and a button.

Let’s see the View Model first:

    public class MainViewModel
    {
        public string WpText { get; set; }
        public string MdText { get; set; }

        public void ConvertText()
        {
            MdText = $"Converted {WpText}";
        }
    }

Okay, so we have two strings, and a method that populates the second string with the first. As per the linked post, the plumbing for the view model is very simple; first, it’s registered in ConfigureServices:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<MainViewModel, MainViewModel>();
        }

Then it’s injected into the Razor view:

@page "/"
@inject ViewModels.MainViewModel MainViewModel

In fact, the next part is much simpler than I thought it would be. To bind a view model property to the view, you just use the syntax bind:

<div class="container">
    <div class="row">
        <div class="form-group col-md-6">
            <label for="WpText">Wordpress Text</label>
            <input type="text" @[email protected] class="form-control" id="WpText" name="WpText"/>
        </div>

        <div class="form-group col-md-6">
            <label for="MdText">Markdown</label>
            <input type="text" @[email protected] class="form-control" id="MdText" name="MdText"/>
        </div>
    </div>
    <div class="row">
        <div class="form-group col-md-12">
            <input type="button" value="Convert" @[email protected](() => MainViewModel.ConvertText()) class="form-control" id="Submit" />
        </div>
    </div>
</div>

Just to point out one thing that tripped me up before I leave this: the event handlers that relate to Blazor must be prefixed with an at symbol (@).

References

https://www.nativoplus.studio/blog/blazor-data-binding-2/

Adding Logging to Client Side Blazor

Whilst there are some pre-built libraries for this, I seemed to be getting Mono linking errors. What finally worked for me was to install the pre-release versions of:

Install-Package Microsoft.Extensions.Logging -Version 3.0.0-preview6.19304.6
Install-Package Microsoft.Extensions.Logging.Console -Version 3.0.0-preview6.19304.6

Now, in your View Model, accept the Logger:

public MyViewModel(ILogger<MyViewModel> logger)

Then you can log as normal:

_logger.LogInformation("Hello, here's a log message");

You should now see the debug message in the F12 console.

You might be wondering why you don’t need to explicitly inject the logging capability; the reason is that:

BlazorWebAssemblyHost.CreateDefaultBuilder()            

Does that for you.

Casting a C# Object From its Parent

Have you ever tried to do something akin to the following:

[Fact]
public void ConvertClassToSubClass_Converts()
{
    // Arrange
    var parentClass = new SimpleTestClass();
    parentClass.Property1 = "test";
 
    // Act
    var childClass = parentClass as SimpleTestSubClass;
 
    // Assert
    Assert.Equal("test", childClass.Property1);
}

This is a simple Xunit (failing) test. The reason is fails is because you (or I) am trying to cast a general type to a specific, and C# is complaining that this may not be possible; consequently, you will get null (or for a hard cast, you’ll get an InvalidCastException.

Okay, that makes sense. After all, parentClass could actually be a SimpleTestSubClass2 and, as a result, C# is being safe because there’s (presumably – I don’t work for MS) too many possibilities for edge cases.

This is, however, a solvable problem; there are a few ways to do it, but you can simply use reflection:

public TNewClass CastAsClass<TNewClass>() where TNewClass : class
{
 
    var newObject = Activator.CreateInstance<TNewClass>();
    var newProps = typeof(TNewClass).GetProperties();
 
    foreach (var prop in newProps)
    {
        if (!prop.CanWrite) continue;
 
        var existingPropertyInfo = typeof(TExistingClass).GetProperty(prop.Name);
        if (existingPropertyInfo == null || !existingPropertyInfo.CanRead) continue;
        var value = existingPropertyInfo.GetValue(_existingClass);
        
        prop.SetValue(newObject, value, null);
    }
 
    return newObject;
}

This code will effectively transfer any class over to any other class.

If you’d rather use an existing library, you can always use this one. It’s also Open Source on Git Hib.

The Evolution of the Switch Statement (C#8)

Most languages have a version of the switch statement as far as I’m aware; I must admit, I don’t remember one from Spectrum Basic, but ever since then, I don’t think I’ve come across a language that doesn’t have one. The switch statement in C was interesting. For example, the following was totally valid:

switch (value)
{
    case 1:
        printf("hello ");
    case 2:
        printf("world");        
}

If you gave it a value of 1 would print “hello world”. When C# came out, they insisted on using breaks at the end of case statements, or having no code (admittedly there were a few bugs in C caused by accidentally leaving break statements out):

            int value = 1;
            switch (value)
            {
                case 1:
                    Console.Write("hello ");
                    break;
                case 2:
                    Console.Write("world");
                    break;
            }

Anyway, fast forward around 17 years to C# 7.x, and it basically has the same switch statement; in fact, as far as I’m aware, you could write this switch statement in C# 1.1 and it would compile fine. There’s nothing wrong with it, so I imagine MS were thinking why fix it if it’s not broken.

There are limitations, however; for example, what if I want to return the string, like this:

            int value = 1;
            string greeting = string.Empty;
            switch (value)
            {
                case 1:
                    greeting = "hello ";
                    break;
                case 2:
                    greeting = "world";
                    break;
            }

            Console.WriteLine(greeting);

Now it looks a bit cumbersome. What if we could write it like this:

            int value = 1;
            string greeting = value switch
            {
                1 => "hello ",
                2 => "world",
                _ => string.Empty
            };

            Console.WriteLine(greeting);

From C# 8, you can do just that. The switch statement will return its value. The case syntax is disposed of, and there’s no need for a break statement (which, to be fair, can encourage people to write large swathes of code inside the switch statement – if you don’t believe me then have a look in the Asp.Net Core source!).

And that’s not all. Pattern matching has also been brought in; for example, take the following simple class structure:

    interface IAnimal
    {
        void Eat();
        void Sleep();            
        string Name { get;}
    }

    class Dog : IAnimal
    {
        public string Name { get => "Fido"; }

        public void Eat()
        {
            Console.WriteLine("Dog Eats");
        }

        public void Sleep()
        {
            Console.WriteLine("Dog Sleeps");
        }
    }

    class Cat : IAnimal
    {
        public string Name { get => "Lemmy"; }

        public void Eat()
        {
            Console.WriteLine("Cat Eats");
        }

        public void Sleep()
        {
            Console.WriteLine("Cat Sleeps");
        }
    }

We can put that into a switch statement like this:

            IAnimal animal = new Cat();
            string greeting = animal switch
            {
                Dog d => $"hello dog {d.Name}",
                Cat c => $"hello cat {c.Name}",                
                _ => string.Empty
            };

            Console.WriteLine(greeting);

We can actually do better that this (obviously better is a relative term). Let’s say that we wanted to do something specific for our particular cat:

            IAnimal animal = new Cat();
            string greeting = animal switch
            {
                Dog d => $"hello dog {d.Name}",
                Cat c when c.Name == "Lemmy" => $"Hello motorcat!",
                Cat c => $"hello cat {c.Name}",                
                _ => string.Empty
            };

            Console.WriteLine(greeting);

It’s a bit of a silly and contrived example, but it does illustrate the point; further, if you switch the case statements around for the general and specific form of Cat, you’ll get a compile error!

ReadOnly Entity Framework

Ever come across a situation where you want to use an Entity Framework data layer in a little tool or report, but ended up reverting to Ado.Net or a different ORM because EF is a little bit like a Heisenberg Framework (it changes things that it looks at)? You might have a seed method that tries to update data, or a migration that you don’t want to apply.

Apologies in advance if this seems like stating the bloody obvious; but it didn’t seem obvious to me at the time. If there’s a neater way to do this then please let me know.

Anyway, I recently had this issue, and came up with the idea of a ReadOnly DBContext. For example, your main DBContext might look like this:

    public class MyDbContext : DbContext, IMyDbContext
    {
        static MyDbContext()
        {            
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, Configuration>());
        }
 
        public MyDbContext()
            : base("connection-string")
        {
            
            
        }
 
        public MyDbContext(string connectionString)
            : base(connectionString)
        {
 
 
        }
 
        public DbSet<Entity1> Entity1 { get; set; }
        public DbSet<Entity2> Entity2 { get; set; }
 
        void IMyDbContext.SaveChanges()
        {
            base.SaveChanges();
        }
 
        Task IMyDbContext.SaveChangesAsync()
        {
            return base.SaveChangesAsync();
        }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Entity1>()
                .HasOptional(a => a.Field2)
                .WithMany();            
  
            base.OnModelCreating(modelBuilder);
        }
    }

Making a ReadOnly version of this is pretty much removing the code; for example:

    public class MyReadOnlyDbContext : DbContext, IMyDbContext
    {
        static MyReadOnlyDbContext()
        {            
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyReadOnlyDbContext, Configuration>());
        }
 
        public MyReadOnlyDbContext()
            : base("connection-string")
        {
            
            
        }
 
        public MyReadOnlyDbContext(string connectionString)
            : base(connectionString)
        {
 
 
        }
 
        public DbSet<Entity1> Entity1 { get; set; }
        public DbSet<Entity2> Entity2 { get; set; }
 
        void IMyDbContext.SaveChanges()
        {

        }
 
        Task IMyDbContext.SaveChangesAsync()
        {
		  return Task.CompletedTask;

        }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Entity1>()
                .HasOptional(a => a.Field2)
                .WithMany();
  
            base.OnModelCreating(modelBuilder);
        }
    }

An easy way to return the read only version, rather than the main version is via a DbContextGenerator:

public class DbContextGenerator : IDbContextGenerator
{
    private readonly AppSettings appSettings;        
 
    public DbContextGenerator(AppSettings appSettings)
    {
        this.appSettings = appSettings;            
    }
 
    public IMyDbContext GenerateDbContext()
    {            
        if (appSettings.ReadOnly)
        {
            return new MyDbReadOnlyContext(appSettings.DatabaseConnectionString);
        }
        return new MyDbContext(appSettings.DatabaseConnectionString);                        
    }
}

This can be registered in the IoC and will return a DB Context based on a read only flag.

It’s worth noting that if your model doesn’t match, it will likely crash. It’s also worth noting that if you’re reading this article and trying to work out how you can use EF without having it manage the DB then it’s probably because something, somewhere, went wrong: this isn’t a suggestion for a new way to use EF, it’s a way to use EF in a temporary fashion.

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: