Category Archives: .Net Core

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.

The “LegacyFrameworkPackages” parameter is not supported by the “ResolveFrameworkReferences” task

I got this error recently while updating a project that I’m working on. It had been ported from WinForm to .Net Core 3.0, and worked fine – but suddenly I started getting errors where it claimed to not know what Form was. The output showed the error:

The “LegacyFrameworkPackages” parameter is not supported by the “ResolveFrameworkReferences” task

Unbeknownst to me, MS have changed the namespace for desktop apps; where previously your csproj might look like this:

<Project Sdk="Microsoft.NET.Sdk">
 
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <LangVersion>8.0</LangVersion>
    <NullableReferenceTypes>true</NullableReferenceTypes>
    
    <AssetTargetFallback>uap10.0.18362</AssetTargetFallback>
    <UseWindowsForms>true</UseWindowsForms>
  </PropertyGroup>

It now needs to look reference the WindowsDesktop SDK:

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

Mocking IConfiguration Extension Method

In this post I wrote about the use of app settings in Asp.Net Core. One thing that I didn’t cover at the time was the fact that, as an extension library, the configuration extensions weren’t very easy to include in unit tests. Of course the intention is that you read the configuration at the start, pass through a model class and no mocking is required.

However, sometimes you’ll find yourself wanting to mock out a particular setting. Before I get into this, this post is heavily based on this article which describes the same process.

The following is a code sample using Moq:

            var configuration = new Mock<IConfiguration>();

            var configurationSection = new Mock<IConfigurationSection>();
            configurationSection.Setup(a => a.Value).Returns("testvalue");

            configuration.Setup(a => a.GetSection("TestValueKey")).Returns(configurationSection.Object);            

This will cause any call to get the app settings key “TestValueKey” to return “testvalue”. As is stated in the linked article, whilst GetValue is an extension method, GetSection is not, but is (internally) called by GetValue.

References

https://dejanstojanovic.net/aspnet/2018/november/mocking-iconfiguration-getvalue-extension-methods-in-unit-test/

Read a Document in a .Net Core Application Baked into the Project File

This isn’t a difficult thing to achieve, but it is one that frequently has me reaching for Google to get the exact syntax. By creating this post (I create all my posts on OneNote first), it’s now offline for me.

There’s more than one way to do this; I’ve covered two. All the examples here are using a CSV file from an Assets folder:

Embedded Resource

These are embedded into the compiled assembly; which means in order to change them, you would need to recompile your code. This works well for images, but less well for data files.

First, you need to add your resource to your project, and set the properties to be an embedded resource:

Because it’s embedded, copying makes no sense. To read the file:

public string GetResourceTextFile(string filename)
{
    using Stream stream = this.GetType().Assembly.
                       GetManifestResourceStream($"SalesOrder.Generate.{filename}");
    using StreamReader sr = new StreamReader(stream);                           
            
    return sr.ReadToEnd();
}

Content

This allows you to include a file within your project; however, content files are not compiled. Combined with the “Copy To Output Directory” they place files in the binary directory of your project. The advantage here is that you can change this file after compilation:

Because this just copies the file to the executing directory, it’s easier to read the file:

public string GetContentTextFile(string filename)
{
    return File.ReadAllText($"Assets/{filename}");
}

References

https://stackoverflow.com/questions/145752/what-are-the-various-build-action-settings-in-visual-studio-project-properties

My XUnit Tests won’t run in a .Net Standard 2.0 Class Library

Firstly, this isn’t a bug, or something that you might have done wrong; it’s intentional. Essentially, you can’t run a .Net Standard Library, so your tests aren’t runnable.

Okay – so I want to convert to .Net Core 3.0!

Yep – that’s exactly what you want, and it’s this easy; open up the csproj file – it’ll look like this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

And replace it with this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

And that’s it – your tests should now run!

Creating a Windows Service using .Net Core 2.2

Up until very recently, creating a Windows Service was the domain of the .Net Framework. However, since the release of the Windows Compatibility Pack that has all changed. In this article, we’ll create a .Net Core Windows Service from scratch.

I’m using the preview version of Visual Studio 2019 for this post. As far as I’m aware, there is absolutely no functional difference between this and VS2017; however, the initial New Project screen does look a little different.

Create the Project

There are no “New Windows Service (.Net Core)” options in Visual Studio, so we’re just going to create a console application (everything is a console application in .Net Core):

The .Net Core application can target .Net Core 2.2:

Windows Compatibility

The next step is to install the Windows Compatibility NuGet package:

Install-Package Microsoft.Windows.Compatibility

Write the Service

Let’s start with the main method:

static void Main(string[] args)
{
    using (var service = new TestSevice())
    {
        ServiceBase.Run(service);
    }
}

You’ll need to Ctrl-. ServiceBase. TestService doesn’t exist yet, so let’s create that:

internal class TestSevice : ServiceBase
{
    public TestSevice()
    {
        ServiceName = "TestService";
    }

    protected override void OnStart(string[] args)
    {
        string filename = CheckFileExists();
        File.AppendAllText(filename, $"{DateTime.Now} started.{Environment.NewLine}");
    }

    protected override void OnStop()
    {
        string filename = CheckFileExists();
        File.AppendAllText(filename, $"{DateTime.Now} stopped.{Environment.NewLine}");
    }

    private static string CheckFileExists()
    {
        string filename = @"c:\tmp\MyService.txt";
        if (!File.Exists(filename))
        {
            File.Create(filename);
        }

        return filename;
    }

}

Not exactly a complicated service, I’ll grant you.

Installing

For Framework apps, you could use InstallUtil, but if you try that on a Core app, you get an annoyingly vague error! Instead, you need to find the place where the binary has been compiled; for example:

C:\Users\pcmic\source\repos\ConsoleApp3\ConsoleApp3\bin\Debug\netcoreapp2.2

Now, launch a command prompt as admin, and type the following:

>sc create [service name] binpath=[full path to binary]

For example:

>sc create pcmtestservice binpath=C:\Users\pcmic\source\repos\ConsoleApp3\ConsoleApp3\bin\Debug\netcoreapp2.2\ConsoleApp3.exe

You should get the response:

[SC] CreateService SUCCESS

You can then either start the service from here:

>sc start pcmtestservice

Or locate it in the services utility and start it from there. You should now be able to start and stop the service and see it logging the events as you do so.

If you need to remove the service, use:

>sc delete pcmtestservice

References

https://stackoverflow.com/questions/7764088/net-console-application-as-windows-service

Short Walks – 406 Error While Creating a .Net Core Api

I’m afraid this is another of those: “What has AddMvc()” ever done for us posts.  Today, I was creating a brand new .Net Core 2.1 Api and, instead of calling AddMvc in ConfigureServices, I instead used AddMvcCore:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore();

When I tried to access the API, I got a 406 error.  The fix is very simple (and one that using AddMvc() does for you:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore()
            .AddJsonFormatters();

Unity Lifetime Manager

If you’ve ever used an IoC container, you’ll know that one of their benefits and burdens is that they abstract away from you the hassle of managing your dependencies. Just declare your interfaces as constructor parameters and then register those dependencies at startup, and the IoC container will propogate your class. Your registration may look like this:

    container.RegisterType<IMyService, MyService>();

But what about when your class has state? For example, what if I have this sort of thing:

    container.RegisterType<IMyData, MyData>();

Here we’re using unity, but it appears that the default behaviour for most IoC containers is transient – that is, they are created each time they are resolved. This is important, not just because you will lose data that you thought you had (in fact that’s one of the better scenarios – because it’s obvious that it’s not behaving how you expect), but because if you’re caching results of queries and so forth, you might find your application is going back for data that you thought it already had. Here’s an example, using Unity, that proves this:

static void Main(string[] args)
{
    var container = new UnityContainer();
 
    container.RegisterType<IMyService, MyService>();
    container.RegisterType<IMyData, MyData>();
 
    container.Resolve<IMyData>().Test = "testing";
    container.Resolve<IMyService>().TestFunction();
 
    Console.ReadLine();
}

The service class might look like this:

public interface IMyService
{
    void TestFunction();
}
 
public class MyService : IMyService
{
    private readonly IMyData myData;
 
    public MyService(IMyData myData)
    {
        this.myData = myData;
    }
 
    public void TestFunction()
    {
        Console.WriteLine($"Test Data: {myData.Test}");
    }
}

And the data class:

public interface IMyData
{
    string Test { get; set; }
}
public class MyData : IMyData
{
    public string Test { get; set; }
}

If you run that, you’ll see that the output is:

Test Data: 

Different IoC containers have slightly different life times – in fact, in the .Net Core IoC, you have to now explicitly register as Singleton, Transient or Scoped. In Unity, you can do something like this:

static void Main(string[] args)
{
    var container = new UnityContainer();
 
    container.RegisterType<IMyService, MyService>(new ContainerControlledLifetimeManager());
    container.RegisterType<IMyData, MyData>(new ContainerControlledLifetimeManager());
 
    container.Resolve<IMyData>().Test = "testing";
    container.Resolve<IMyService>().TestFunction();
 
    Console.ReadLine();
}

Creating a Basic Web Site from an Asp.Net Core Empty Project

I recently wanted to do a very quick proof of concept, regarding the use of setInterval versus setTimeout after reading that setTimeout was referable if you were calling the same function very rapidly. I thought I’d note down my journey from File -> New Project to having the POC running so that next time, I don’t have to re-lookup the various parts.

File -> New Project

If you create a brand new Asp.Net Core 2.1 project, select empty project, and then run the generated code, you’ll see this:

This is generated by a line in Startup.cs:

app.Run(async (context) =>
{
    await context.Response.WriteAsync("Hello World!");
});

The target here is to get to a situation where the blank app is serving an HTML page with some attached Javascript as fast as possible. Here, I’ve got exactly three steps.

Step 1 – Create the HTML File

The application can only serve static files (HTML is considered a static file) from the wwwroot folder. The internal structure of this folder doesn’t matter, but that’s where your file must go:

The contents of this file are as follows:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <p>test</p>
</body>
</html>

This won’t actually do anything yet, because by default, Asp.Net Core does not serve static files, nor does it know the enormous significance of naming something “Index”.

Step 2 – Configure Asp.Net

Startup.cs is where all the magic happens; this is what it looks like out of the box:

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        
    }
 
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
 
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

The `context.Response.WriteAsync` goes, and instead we tell Asp.Net Core to serve static files, and the call to `UseDefaultFiles` means that it will search for Index or Default files. It’s also worth pointing out that the order of these matters:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
            
    app.UseDefaultFiles();
    app.UseStaticFiles();                                    
}

Now it loads the Index.html. So technically it was only two steps – although we haven’t referenced any Javascript yet.

Step 3 – Adding the javascript… and let’s do something funky

Change the HTML to give the paragraph an ID and an absolute position. Also, reference the file site.js:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="site.js"></script>
</head>
<body>
    <p id="testElement" style="position:absolute">test</p>
</body>
</html>

Obviously, without adding site.js, nothing will happen (it also needs to be in wwwroot):

The Javascript code for that new file is here:

var divxPos = 0;
 
window.onload = function () {
    runCode();
};
 
function runCode() {
    var test = document.getElementById("testElement");    
    test.style.left = divxPos++ + 'px';    
 
    setTimeout(() => runCode(), 50);
};

If you run it, you’ll find the text running away with itself!

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