Friday, March 30, 2018

Entity Framework Core 2.0–Owned types

EF Core 2.0 (re)introduces the concept of Complex types which are called Owned types in EF Core. I find the new naming confusing but hey that’s me…

Anyway let’s have a look at how we can use these Complex Owned types. We’ll start by creating a Supplier class with an Address;

Important to notice is that the Address does not have it’s own Id but is embedded into the Supplier class.

To configure the Owned types mapping, you have to use the OwnedOne method in the mapping file. If you want to further configure the properties of the Owned type, you’ll have to repeat the statement for every property in the Owned type:

That's it!

Thursday, March 29, 2018

Debugging an ASP.NET Core project in IIS

After changing my launch target to IIS for my ASP.NET Core project, I got the following error from Visual Studio:

image

With a recent update to Visual Studio 2017(15.3), Microsoft added support for debugging ASP.NET Core applications against IIS. To be able to use you have to modify your existing Visual Studio Installation. So open up the Visual Studio Installer and select the Development time IIS support component which is listed as optional component under the ASP.NET and web development workload.

image

This will install the ASP.NET Core Module which is a native IIS module required to run ASP.NET Core applications on IIS. Click on Modify to start the installation.

After the installation has completed, restart Visual Studio and try to run your app again.

More information: https://blogs.msdn.microsoft.com/webdev/2017/07/13/development-time-iis-support-for-asp-net-core-applications/

Wednesday, March 28, 2018

Azure Strategy and Implementation Guide

Microsoft created another free e-book for every organisation that thinks about moving to the cloud: the Azure Strategy and Implementation Guide for IT Organizations. This book will guide you through the first steps of you cloud implementation process.
image
What is covered:
  • Chapter 1: Governance – This chapter covers the starting points, from the aspirational “digital transformation” to the important tactical steps of administration and resource naming conventions. Get an overview of topics such as envisioning, to cloud readiness, administration, and security standards and policy.
  • Chapter 2: Architecture – This section takes a longer look at security, touches on cloud design patterns, and provides several visual representations to help you understand network design.
  • Chapter 3: Application development and operations – Here, we cover backup and disaster recovery, as well as application development from an IT operations and management perspective. You’ll learn about the culture of DevOps as well as monitoring and Infrastructure as Code (IaC).
  • Chapter 4: Service management – No, IT does not become obsolete when an organization moves to the cloud! This chapter focuses on service management and optimization, along with the day-to-day details of how to stay informed of the Azure roadmap, updates, and where to go when you need support.
You can copy your free copy of the e-book here (subscription required): https://azure.microsoft.com/en-us/resources/azure-strategy-and-implementation-guide/en-us/

Friday, March 23, 2018

Impress your colleagues with your knowledge about... the DispatchProxy class.

Sometimes when working with C# you discover some hidden gems. Some of them very useful, other ones a little bit harder to find a good way to benefit from their functionality. One of those hidden gems that I discovered some days ago is the DispatchProxy class.

DispatchProxy is a new class in .NET Core that allows you to apply Aspect Oriented Programming techniques using interception.

Let’s try it out by creating a really simple LogInterceptor:

The DispatchProxy class is a little cumbersome and we have to capture our target method using a little dynamic magic(casting would have worked as well):

Now let’s create an interface and a corresponding implementation:

As a final step we create an intercepted version of our class and invoke our method:

Here is our output:

image

Thursday, March 22, 2018

Swashbuckle : Allow file import through the Swagger UI

One of the API’s I’m building allows you to import files to a database.

To simplify testing I wanted to allow the consumers of my API to test the API directly through the Swagger UI. Problem is that out of the box Swashbuckle(the Swagger implementation for .NET) has no clue how to interprete the IFormFile.

Let’s fix that by introducing an IOperationFilter:

And let’s not forget to register that IOperationFilter in our Startup.cs file:

Now if we run our application and browse to the swagger endpoint(/swagger), when we try to execute our Upload operation, we get a nice Import button:

image

Wednesday, March 21, 2018

NHibernate supports .NET Core!

The NHibernate team is back on a roll! After a previous announcement where they released the long awaited(pun intended) async/await support, they are back again with some other great news. NHibernate 5.1 is released with the support of .NET Core 2.0 and .NET Standard 2.0.

NHibernate-logo.svg

I’m missing way too many features in EF Core, so I’m glad that at least we got another option back.

Tuesday, March 20, 2018

Entity Framework Core 2.0–DbContext pooling

Version 2.0 of EF Core introduces a new way to register your DbContext that transparently introduces a pool of reusable DbContext instances.

This was the code you had to use before 2.0:

Typically this code resulted in creating a new DbContext for each request which introduces an extra performance penalty for your requests.

In EF Core 2.0 you can replace this by:

If this method is used, at the time a DbContext instance is requested by a controller it will first check if there is an instance available in the pool. Once the request processing finalizes, any state on the instance is reset and the instance is itself returned to the pool.

Warning: As all DbContext instances should be completely equal, you are limited in what you can do in the OnConfiguring() method of the DbContext.

Monday, March 19, 2018

Entity Framework Core - No executable found matching command "dotnet-ef"

After adding the EntityFramework nuget package to my ASP.NET Core project and creating our DbContext(see below) I was ready to generate a first migration :

I opened the Package Manager Console in Visual Studio, browsed to the project folder(!),  and executed dotnet ef. I ended up with the following error message:

dotnet : No executable found matching command "dotnet-ef"

At line:1 char:1

+ dotnet ef

+ ~~~~~~~~~

    + CategoryInfo          : NotSpecified: (No executable f...and "dotnet-ef":String) [], RemoteExcep

tion

    + FullyQualifiedErrorId : NativeCommandError

To solve this install the following 2 extra packages:

  • Microsoft.EntityFrameworkCore.Tools: Contains the Entity Framework Core Package Manager Console Tools. Includes Scaffold-DbContext, Add-Migration, and Update-Database.
  • Microsoft.EntityFrameworkCore.Tools.DotNet: Contains the Entity Framework Core .NET Command-line Tools. Includes dotnet-ef.

Remark: When trying to install the Microsoft.EntityFrameworkCore.Tools.DotNet package, I got the following error message:

image

I solved it by adding the package directly to the csproj file:

After doing that run a dotnet restore first. If you now try to execute dotnet ef, it should work:

image

Friday, March 16, 2018

ASP.NET Core Docker error: An assembly specified in the application dependencies manifest (MyApp.deps.json) was not found

Yesterday I had some trouble to get my docker build up and running. However after I succeeded and tried to run my container using docker-compose up, I got the following error message in the container log:

An assembly specified in the application dependencies manifest (MyApp.deps.json) was not found:

    package: 'Microsoft.AspNetCore.Antiforgery', version: '2.0.1'

    path: 'lib/netstandard2.0/Microsoft.AspNetCore.Antiforgery.dll'

  This assembly was expected to be in the local runtime store as the application was published using the following target manifest files:

aspnetcore-store-2.0.3.xml

The problem is caused by the fact that the ASP.NET Core SDK version on the build image(2.0.0) and the referenced version in my project(2.0.3) didn’t match. Easiest solution I could find was resetting the package reference to 2.0.0 in my csproj file:

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

<PropertyGroup>

    <TargetFramework>netcoreapp2.0</TargetFramework>

    <DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>

  </PropertyGroup>

  <ItemGroup>

    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />

  </ItemGroup>

  <ItemGroup>

    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />

</ItemGroup>

</Project>

After doing that I had to stop and delete the previously created container and build and run a new instance using docker-compose build and docker-compose up.

Thursday, March 15, 2018

ASP.NET Core Docker Build error - COPY failed: no source files were specified

Last week I had some time to play with the support for Docker in Visual Studio.

Creating the Docker enabled project

First thing I tried was creating a simple ASP.NET Core application with Docker enabled:

  • Open Visual Studio
  • Go to File –> New Project. Select the Web section and choose the ASP.NET Core Web Application template. Click OK.

image

  • On the next screen choose the Web Application template(or any other) and make sure that the Enable Docker Support checkbox is checked. Click OK to create the project.

image

  • 2 projects are created:
    • One Docker-Compose project that contains a yaml configuration to compose multiple containers
    • One web application project that contains a Dockerfile to compile and build your docker container.

Running the application in a docker container

  • Now that the application is created, it is time to build and run the application.
  • I opened a command prompt with the path set to the project containing my dockerfile and invoked the docker build command. Unfortunately this failed with the following error message:

C:\Projects\test\MyFirstContainer\WebApp1>docker build .

Sending build context to Docker daemon   4.73MB

Step 1/17 : FROM microsoft/aspnetcore:2.0 AS base

---> 9cd3adf8e0bd

Step 2/17 : WORKDIR /app

---> Using cache

---> 4a6bbedae1c7

Step 3/17 : EXPOSE 80

---> Using cache

---> 7a79975eb640

Step 4/17 : FROM microsoft/aspnetcore-build:2.0 AS build

---> e9127190cede

Step 5/17 : WORKDIR /src

Removing intermediate container 0926a125a0ca

---> bdfc28e52021

Step 6/17 : COPY *.sln ./

COPY failed: no source files were specified

       
  • This was not exactly what I expected. The way that Visual Studio sets up the docker file configuration is so that you are expected to use docker-compose build in the solution folder and not docker build in the specific project. So let’s try that:

C:\Projects\test\MyFirstContainer>docker-compose build
Building MyFirstContainer
Step 1/17 : FROM microsoft/aspnetcore:2.0 AS base
  ---> 9cd3adf8e0bd
Step 2/17 : WORKDIR /app
  ---> Using cache
  ---> 4a6bbedae1c7
Step 3/17 : EXPOSE 80
  ---> Using cache
  ---> 7a79975eb640
Step 4/17 : FROM microsoft/aspnetcore-build:2.0 AS build
  ---> e9127190cede
Step 5/17 : WORKDIR /src
Removing intermediate container c9c93c95e2ca
  ---> b9d9b88abe4a
Step 6/17 : COPY *.sln ./
  ---> 46f162cf683d
Step 7/17 : COPY MyFirstContainer/WebApp1.csproj MyFirstContainer/
  ---> 1180f56eecf1
Step 8/17 : RUN dotnet restore
  ---> Running in 36763ba9c396
/usr/share/dotnet/sdk/2.1.4/NuGet.targets(227,5): warning MSB3202: The project file "/src/docker-compose.dcproj" was not found. [/src/MyFirstContainer.sln]
/src/docker-compose.dcproj : warning NU1503: Skipping restore for project '/src/docker-compose.dcproj'. The project file may be invalid or missing targets required for restore. [/src/MyFirstContainer.sln]
  Restoring packages for /src/MyFirstContainer/WebApp1.csproj...
  Restoring packages for /src/MyFirstContainer/WebApp1.csproj...
  Restore completed in 2.46 sec for /src/MyFirstContainer/WebApp1.csproj.
  Installing Microsoft.DotNet.PlatformAbstractions 2.0.0.
  Installing Microsoft.Extensions.DependencyModel 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Core 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Razor.ViewCompilation 2.0.0.
  Installing Microsoft.AspNetCore.DataProtection.Extensions 2.0.0.
  Installing Microsoft.EntityFrameworkCore 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.TagHelpers 2.0.0.
  Installing Microsoft.EntityFrameworkCore.Design 2.0.0.
  Installing Microsoft.Extensions.Identity.Core 2.0.0.
  Installing Microsoft.AspNetCore.Server.Kestrel.Core 2.0.0.
  Installing Microsoft.EntityFrameworkCore.SqlServer 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Razor 2.0.0.
  Installing Microsoft.VisualStudio.Web.BrowserLink 2.0.0.
  Installing Microsoft.Net.Http.Headers 2.0.0.
  Installing Microsoft.Extensions.Identity.Stores 2.0.0.
  Installing Microsoft.AspNetCore.HttpOverrides 2.0.0.
  Installing Microsoft.AspNetCore.Http 2.0.0.
  Installing Microsoft.EntityFrameworkCore.Sqlite.Core 2.0.0.
  Installing Microsoft.CodeAnalysis.Razor 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.RazorPages 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Abstractions 2.0.0.
  Installing Microsoft.EntityFrameworkCore.InMemory 2.0.0.
  Installing Microsoft.AspNetCore.WebUtilities 2.0.0.
  Installing Microsoft.AspNetCore.StaticFiles 2.0.0.
  Installing Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.Facebook 2.0.0.
  Installing Microsoft.AspNetCore.WebSockets 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Razor.Extensions 2.0.0.
  Installing Microsoft.AspNetCore.DataProtection 2.0.0.
  Installing Microsoft.AspNetCore.NodeServices 2.0.0.
  Installing Microsoft.AspNetCore.Rewrite 2.0.0.
  Installing Microsoft.AspNetCore.ResponseCompression 2.0.0.
  Installing Microsoft.Extensions.Localization.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Razor.Runtime 2.0.0.
  Installing Microsoft.AspNetCore.SpaServices 2.0.0.
  Installing Microsoft.AspNetCore.Session 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Formatters.Json 2.0.0.
  Installing Microsoft.AspNetCore.ResponseCaching 2.0.0.
  Installing Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore 2.0.0.
  Installing Microsoft.AspNetCore.Http.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Localization 2.0.0.
  Installing Microsoft.AspNetCore.Identity 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.DataAnnotations 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Cors 2.0.0.
  Installing Microsoft.AspNetCore.Http.Extensions 2.0.0.
  Installing Microsoft.AspNetCore.Razor 2.0.0.
  Installing Microsoft.EntityFrameworkCore.Sqlite 2.0.0.
  Installing Microsoft.AspNetCore.ResponseCaching.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.ApiExplorer 2.0.0.
  Installing Microsoft.AspNetCore.Localization 2.0.0.
  Installing Microsoft.AspNetCore.Identity.EntityFrameworkCore 2.0.0.
  Installing Microsoft.AspNetCore.Authorization 2.0.0.
  Installing Microsoft.AspNetCore.Http.Features 2.0.0.
  Installing Microsoft.AspNetCore.Cryptography.Internal 2.0.0.
  Installing Microsoft.AspNetCore.Cors 2.0.0.
  Installing Microsoft.AspNetCore.DataProtection.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.OpenIdConnect 2.0.0.
  Installing Microsoft.AspNetCore.CookiePolicy 2.0.0.
  Installing Microsoft.AspNetCore.Cryptography.KeyDerivation 2.0.0.
  Installing Microsoft.AspNetCore.Authorization.Policy 2.0.0.
  Installing Microsoft.AspNetCore.Diagnostics.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.AzureAppServicesIntegration 2.0.0.
  Installing Microsoft.AspNetCore.Localization.Routing 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.Twitter 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.OAuth 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.MicrosoftAccount 2.0.0.
  Installing Microsoft.Extensions.Hosting.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.Cookies 2.0.0.
  Installing Microsoft.EntityFrameworkCore.Relational 2.0.0.
  Installing Microsoft.AspNetCore.Server.HttpSys 2.0.0.
  Installing Microsoft.EntityFrameworkCore.Tools 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.Formatters.Xml 2.0.0.
  Installing Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Routing.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Razor.Language 2.0.0.
  Installing Microsoft.AspNetCore.DataProtection.AzureStorage 2.0.0.
  Installing Microsoft.AspNetCore.Hosting.Abstractions 2.0.0.
  Installing Microsoft.Extensions.Localization 2.0.0.
  Installing Microsoft.AspNetCore.MiddlewareAnalysis 2.0.0.
  Installing Microsoft.AspNetCore.Mvc.ViewFeatures 2.0.0.
  Installing Microsoft.AspNetCore.Hosting.Server.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Diagnostics 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.JwtBearer 2.0.0.
  Installing Microsoft.AspNetCore.Owin 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.Core 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.Google 2.0.0.
  Installing Microsoft.AspNetCore.Authentication.Abstractions 2.0.0.
  Installing Microsoft.AspNetCore.Routing 2.0.0.
  Installing Microsoft.AspNetCore.Hosting 2.0.0.
  Installing Microsoft.AspNetCore.Mvc 2.0.0.
  Installing Microsoft.AspNetCore.Authentication 2.0.0.
  Installing Microsoft.AspNetCore.Antiforgery 2.0.0.
  Installing Microsoft.AspNetCore.ApplicationInsights.HostingStartup 2.0.0.
  Installing Microsoft.AspNetCore.AzureAppServices.HostingStartup 2.0.0.
  Installing Microsoft.AspNetCore.Server.IISIntegration 2.0.0.
  Installing Microsoft.AspNetCore.Server.Kestrel 2.0.0.
  Installing Microsoft.AspNetCore 2.0.0.
  Installing Microsoft.AspNetCore.Server.Kestrel.Https 2.0.0.
  Installing Microsoft.AspNetCore.All 2.0.0.
  Generating MSBuild file /src/WebApp1/obj/WebApp1.csproj.nuget.g.props.
  Generating MSBuild file /src/WebApp1/obj/WebApp1.csproj.nuget.g.targets.
  Restore completed in 6.87 sec for /src/WebApp1/WebApp1.csproj.
Removing intermediate container 36763ba9c396
  ---> ee8c5c57438c
Step 9/17 : COPY . .
  ---> 33ea78c746de
Step 10/17 : WORKDIR /src/WebApp1
Removing intermediate container 6ecb9f4e6d4d
  ---> 19720c9e8bf0
Step 11/17 : RUN dotnet build -c Release -o /app
  ---> Running in 24c321df6039
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 32.37 ms for /src/DockerDeployToAppServices/DockerDeployToAppServices.csproj.
  Restore completed in 11.91 ms for /src/DockerDeployToAppServices/DockerDeployToAppServices.csproj.
  DockerDeployToAppServices -> /app/DockerDeployToAppServices.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:04.15
Removing intermediate container 24c321df6039
  ---> cc75478ddcbd
Step 12/17 : FROM build AS publish
  ---> cc75478ddcbd
Step 13/17 : RUN dotnet publish -c Release -o /app
  ---> Running in 94d97edc8747
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 34.93 ms for /src/MyFirstContainer/WebApp1.csproj.
  Restore completed in 28.19 ms for /src/MyFirstContainer/WebApp1.csproj.
  WebApp1-> /src/MyFirstContainer/bin/Release/netcoreapp2.0/WebApp1.dll
  WebApp1-> /app/
Removing intermediate container 94d97edc8747
  ---> 8203313e94a4
Step 14/17 : FROM base AS final
  ---> 7a79975eb640
Step 15/17 : WORKDIR /app
  ---> Using cache
  ---> 2907b766c8a8
Step 16/17 : COPY --from=publish /app .
  ---> 60a1c5e968ac
Step 17/17 : ENTRYPOINT ["dotnet", "WebApp1.dll"]
  ---> Running in 7971f6ac5ddb
Removing intermediate container 7971f6ac5ddb
  ---> 7ef989ef71cb
Successfully built 7ef989ef71cb
Successfully tagged myfirstcontainer:latest

Wednesday, March 14, 2018

Drawing your future

During my flight to Seattle last week I had time to watch some Tedx videos. One of the videos that really inspired me was Draw your future by Patti Dobrowolski.

Time to take out your pencils and start drawing…

Tuesday, March 13, 2018

Angular error: Cannot find module '@angular-devkit/core' (again)

I blogged previously about the following error message:

Cannot find module '@angular-devkit/core'

I got some feedback that the second solution I shared(updating the Angular CLI version) didn’t work for everyone. Turns out that you also need to update the local version of the Angular-CLI:

npm install --save-dev @angular/cli@latest

npm install

More information about updating the Angular CLI can be found in the documentation: https://github.com/angular/angular-cli

Monday, March 12, 2018

Time to give Resharper another try

Over the years I always had a love/hate relationship with Resharper. I loved the rich refactoring options but in the end I always removed Resharper again as the impact on performance was too big. I always prefer a faster IDE(one of the reasons why I’m using VSCode a lot today).

But last week I decided to give Resharper another try. After installing the extension, I started my Visual Studio instance.

The first message I got was not very promising:

ResharperNotification

But we’ll see, I promise that I will try it again for a month and share my experiences in a future blog post.

Happy refactoring!

Friday, March 2, 2018

ElasticSearch - Writing bool queries more elegantly

The default syntax for writing boolean queries using NEST can be quite verbose with deep nesting:

A shorter syntax exists using operators:

More information: https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/bool-queries.html

Thursday, March 1, 2018

ElasticSearch–Should clause

A colleague asked me for help when his ElasticSearch query wasn’t returning the results he expected.

Let me first explain what he tries to achieve using a simplified example:

  • In our search index we have products that are linked to a specific category.
  • We want to search for specific product values AND only return results for the categories we specified
    • In SQL this would translate to a query similar to the following:

‘SELECT * FROM PRODUCTS WHERE (ProductBrand=’Apple’ OR ProductName=’Apple’ ) AND CATEGORY=’Hardware’’ 

Here is the first attempt to write this using NEST:

    We noticed however that instead of executing an AND, we got OR behavior instead. We got all products back where category is ‘Hardware’ but not limited to ‘Apple’ products.

    Why is this happening?

    First important to notice is that the query above does a full text search and is not filter query. Combining multiple clauses with and, or and not logic becomes more subtle. Queries decide not only whether to include a document, but also how relevant that document is.

    ElasticSearch interpretes the query above like this:

    • The must clause says: Please return me all documents where the Category is ‘Hardware’
    • The should clause says: A document is not required to contain ‘Apple’ but if it does, then it should be considered more relevant.

    To fix this, you can either switch to a filter instead of a full text search or specify a minimum_should_match level.

    From the documentation:

    By default, none of the should clauses are required to match, with one exception: if there are no must clauses, then at least one should clause must match.

    Just as we can control the precision of the match query, we can control how many should clauses need to match by using the minimum_should_match parameter, either as an absolute number or as a percentage.

    Wat je eigenlijk wil is dat minstens 1 should clause een resultaat teruggeeft. Dit kan je doen door de "minimum_should_match" instelling te manipuleren:

    Here is the fixed query: