Category Archives: .Net Core

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:

Short Walks – Using AppSettings.json in Asp Net Core

One of the things that is very different when you move to Asp.Net Core is the way that configuration files are treated. This partly comes from the drive to move things that are not configuration out of configuration files. It looks like the days of app.config and web.config are numbered and, in their place, we have AppSettings.Json. Here’s an example of what that new file might look like:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AzureAppSettings": {
    "ApplicationInsightsKey": "1827374d-1d50-428d-92a1-c65fv2d73272"
  }
 
}
 

The old files were very flat and, using the configuration manager, you could simply read a setting; something like this:

var appSettings = ConfigurationManager.AppSettings;
string result = appSettings[key];

So, the first question is: can you still do this? The answer is, pretty much, yes:

public void ConfigureServices(IServiceCollection services)
{            
    IConfigurationBuilder builder = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json");
    Configuration = builder.Build();

    Configuration["AzureAppSettings:ApplicationInsightsKey"]

However, you now have the option of creating a class to represent your settings; something like:

AzureAppSettings azureAppSettings = new AzureAppSettings();
Configuration.GetSection("AzureAppSettings").Bind(azureAppSettings);

If you use this approach then you’ll need an extension library from NuGet:

Install-Package Microsoft.Extensions.Configuration.Binder

Is it better, or worse?

At first glance, it would appear that things have gotten worse; or at least, more complex. However, the previous method had one massive problem: it was a static class. The result being that most people have written their own wrapper around the ConfigurationManager class. We now have a class that can be injected out of the box; alternatively, you can split your configuration up into classes, and pass the classes around; the more I think about this, the better I like it: it makes more sense to have a class or method accept parameters that are necessary for its execution and, arguably, breaks the single responsibility principle if you’re faffing around trying to work out if you have all the operating parameters.

The other advantage here is that the configuration file can now be hierarchical. If you have well designed, small pieces of software then this might not seem like much of an advantage, but if you have 150 settings in your web.config, it makes all the difference.

Setting up Entity Framework Core for a Console Application – One Error at a Time

Entity Framework can be difficult to get started with: especially if you come from a background of accessing the database directly, it can seem like there are endless meaningless errors that appear. In this post, I try to set-up EF Core using a .Net Core Console application. In order to better understand the errors, we’ll just do the minimum in each step; and be guided by the errors.

The first step is to create a .Net Core Console Application.

NuGet Packages

To use Entity Framework, you’ll first need to install the NuGet packages; to follow this post, you’ll need these two (initially) 1:

PM> Install-Package Microsoft.EntityFrameworkCore
PM> Install-Package Microsoft.EntityFrameworkCore.Tools

Model / Entities

The idea behind Entity Framework is that you represent database entities, or tables as they used to be known, with in memory objects. So the first step is to create a model:

namespace ConsoleApp1.Model
{
    public class MyData
    {
        public string FieldOne { get; set; }
 
    }
}

We’ve created the model, so the next thing is to create the DB:

PM> Update-Database

In the package manager console.

First Error – DbContext

The first error you get is:

No DbContext was found in assembly ‘ConsoleApp1’. Ensure that you’re using the correct assembly and that the type is neither abstract nor generic.

Okay, so let’s create a DbContext. The recommended pattern (as described here) is to inherit from DbContext:

namespace ConsoleApp1
{
    public class MyDbContext : DbContext
    {
    }
}

Okay, we’ve created a DbContext – let’s go again:

PM> Update-Database

Second Error – Database Provider

The next error is:

System.InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider.

So we’ve moved on a little. The next thing we need to do is to configure a provider. Because in this case, I’m using SQL Server, I’ll need another NuGet package:

PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer

Then configure the DbContext to use it:

public class MyDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        string cn = @"Server=.\SQLEXPRESS;Database=test-db;User Id= . . .";
        optionsBuilder.UseSqlServer(cn);
 
        base.OnConfiguring(optionsBuilder);
    }
}

And again:

PM> Update-Database

Third Error – No Migrations

Strictly speaking this isn’t an actual error. It’s more a sign that nothing has happened:

No migrations were applied. The database is already up to date.
Done.

A quick look in SSMS shows that, whilst it has created the DB, it hasn’t created the table:

So we need to add a migration? Well, if we call Add-Migration here, we’ll get this: 2

That’s because we need to tell EF what data we care about. So, in the DbContext, we can let it know that we’re interested in a data set (or, if you like, table) called MyData:

public class MyDbContext : DbContext
{
    public DbSet<MyData> MyData { get; set; }

Right – now we can call:

PM> Add-Migration FirstMigration

Fourth Error – Primary Key

The next error is more about EF’s inner workings.:

System.InvalidOperationException: The entity type ‘MyData’ requires a primary key to be defined.

Definitely progress. Now we’re being moaned at because EF wants to know what the primary key for the table is, and we haven’t told it (Entity Framework, unlike SQL Server insists on a primary key). That requires a small change to the model:

using System.ComponentModel.DataAnnotations;
 
namespace ConsoleApp1.Model
{
    public class MyData
    {
        [Key]
        public string FieldOne { get; set; }
 
    }
}

This time,

PM> Add-Migration FirstMigration

Produces this:

    public partial class FirstMigration : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "MyData",
                columns: table => new
                {
                    FieldOne = table.Column<string>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_MyData", x => x.FieldOne);
                });
        }
 
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "MyData");
        }
    }

Which looks much more like we’ll get a table – let’s try:

PM> update-database
Applying migration '20180224075857_FirstMigration'.
Done.
PM> 

Success

And it has, indeed, created a table!

References

https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell

https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext

https://www.learnentityframeworkcore.com/walkthroughs/console-application

Foot Notes

Web API Routing – The Basics

Working with API projects, it’s easy to miss some key rules about the routing. This post is basically the result of some that I missed, and subsequent the investigation. It covers some very basic routing rules, and it certainly not intended to be an exhaustive guide.

.Net Framework

Starting with a .Net Framework Web API, let’s create a new web app:

And add a new controller:

Here’s the code for the controller; as you will see, it’s massively complex, but the good news is that you only need to pay attention to the name of the action, and the code inside it:

public class TestController : ApiController
{
    [HttpGet]
    public IHttpActionResult TestAction()
    {
        return Ok("TestAction Performed");
    }
}

Let’s run the project and navigate to the URL:

How did I know that was the URL? It’s magic, and you can buy some of that magic by sending a cheque for the low, low price of $25 to the address shown at the bottom of the screen.

Actually, it’s defined in WebApiConfig.cs:

Parameters

Where there is more than a single function, one surprising (to me) feature is that the parameters that it accepts is more important to the routing than the name of the controller. Here’s a second action with a parameter:

[HttpGet]
public IHttpActionResult TestAction2(string test)
{
    return Ok("TestAction2 Performed");
}

… and here’s it working:

However, should I not give it the parameter that it craves, it hides away, and instead, we get the first function that’s no too fussy about parameters:

It doesn’t even matter whether I just put some drivel as the controller name; the first criteria is the parameter:

This is because, according to this it follows these criteria:

The default implementation is provided by the ApiControllerActionSelector class. To select an action, it looks at the following:
• The HTTP method of the request.
• The “{action}” placeholder in the route template, if present.
• The parameters of the actions on the controller.

So, if we add the {action} placeholder, that ensures that it uses the correct method:

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
 
    // Web API routes
    config.MapHttpAttributeRoutes();
 
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        //routeTemplate: "api/{controller}/{id}",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

Otherwise, we get a best guess based on the parameters.

.Net Core Web API

The rules have changed since switching to .Net Core; WebApiConfig has gone and, in its place, it a localised routing system.

Here, you tell the class how to handle routing; for example, the following:

[Route("api/[controller]")]

Will result anything decorated with HttpGet being called when the controller is called. The parameters must be explicitly decorated; so passing no parameters would look like this:

[HttpGet]
public string OneTest()
{
    return "TestOne";
}

Whereas, a single parameter would look like this:

[HttpGet("{id}")]
public string aaa(int id)
{
    return "value aaa";
}

If you duplicate the signatures then they are not found. As with the framework version, you can simply tell it to look to the action name that you give it:

[Route("api/[controller]/[action]")]
public class TestController : Controller
{
    [HttpGet]
    public IEnumerable<string> TestActionOne()
    {
        return new string[] { "one value1", "value2" };
    }
 
    [HttpGet]
    public string TestActionTwo()
    {
        return "two value";
    }

But, again, it pays no attention to parameters until you decorate it correctly.

References

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing

Short Walks – Instantiating an Object Without calling the Constructor

One of the things that caught my attention at DDD North was the mention of a way to instantiate an object without calling its constructor.

Disclaimer

Typically, classes have code in their constructors that are necessary for their functionality, so you may find that doing this will cause your program to fall over.

System.Runtime.Serialization

The title of the namespace is probably the first thing that betrays the fact that you shouldn’t be doing this; but we’re already halfway down the rabbit hole!

Here’s some code that will create a class using reflection the normal way:

    static void Main(string[] args)
    {
        var test = Activator.CreateInstance<MyTestClass>();
        test.MyMethod();

        Console.WriteLine("Hello World!");
        Console.ReadLine();
    }

    public class MyTestClass
    {
        public MyTestClass()
        {
            Console.WriteLine("MyTestClass Initialise");
        }

        public string test1 { get; set; }

        public void MyMethod()
        {
            Console.WriteLine("Test MyMethod.");
        }
    }

The output is:

And here’s the code that circumvents the constructor:

        static void Main(string[] args)
        {
            var test2 = FormatterServices.GetUninitializedObject(typeof(MyTestClass)) as MyTestClass;
            test2.MyMethod();

            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }

And we haven’t invoked the constructor: