ASP.NET Core 1.0 pitfalls

Our names are Justyna Setlak, Szymon Matwijów and Julian Pszczołowski. We are students who did an internship in Fingo during 2016 summer holidays.

Our task was to create a server whose API one can use to authenticate and authorize users – something like login in with Facebook – and a web app to manage the server comfortably.

We were using .NET Core 1.0.0, .NET Framework 4.6.1 and Jenkins as a continuous integration tool, which was building, testing and publishing the code. It was really a surprise to us that we had to work in ASP.NET Core 1.0.0 instead of an earlier version.

This ASP.NET was really new at that time, it was released only one month before our internship. We were very keen on working in it, but also quite concerned about it. We didn’t know whether it would be very different from the earlier versions. We didn’t know whether there will be a lot of frameworks working properly. We even didn’t know if there will be posts online that would help us in our work.

Unfortunately, our fears were confirmed and we had some difficulties, especially with bringing ASP.NET Core application to life and integrating it with Jenkins. Here are details of some of the problems we encountered:

Entity Framework

Create repository pattern as Core Library project and run migrations

We wanted to have data source layer as a Core Library project to store our entities, database context and queries. But we couldn’t reference this project to our web applications and run Entity Framework migrations. We solved this problem by a small workaround.

Also, we had to use those CMD commands for migrations in nuget package manager:


cd .\DatabaseLibraryProject
dotnet ef migrations add init
dotnet ef database update

Many to many relationships

Many-to-many relationships without an entity class to represent the join table are not yet supported.

We couldn’t create many-to-many relationships without creating entity class which represented join (association) table. We had to create two separate one-to-many relationships and entity class for the join table.

Creating sample many-to-many relationship – Entity framework documentation

Autofac

We had a lot of factories (one factory – one action). We did not want to register each factory in register module. We wanted to be able to register all the factories that inherit from IActionFactory interface and are located in Fingo.Auth.Domain.*. Here is the code which enabled us to do so:


public class DomainFactoryModule : Module
{
    private const string LibrariesName = "Fingo.Auth.Domain.";

    protected override void Load(ContainerBuilder builder)
    {
        RegisterSubServices(builder);
    }

    private void RegisterSubServices(ContainerBuilder builder)
    {
        var loadableAssemblies = LoadAssemblies();

        builder.RegisterAssemblyTypes(loadableAssemblies.ToArray())
            .Where(t => t.GetInterfaces()
                .Any(i => i.IsAssignableFrom(typeof(IActionFactory))))
            .AsImplementedInterfaces()
            .InstancePerDependency();
    }

    private List<Assembly> LoadAssemblies()
    {
       var deps = DependencyContext.Default;

       return (from compilationLibrary in deps.CompileLibraries
                where compilationLibrary.Name.Contains(LibrariesName)
                select Assembly.Load(new AssemblyName(compilationLibrary.Name)))
                .ToList();
    }
}

Excel files

As of the end of August 2016, there was no framework that could help us in creating or opening .XLS and .XLSX files. Therefore we switched to simple CSV and TSV formats.

Selenium

Selenium was not available for .NET Core either, but there is a workaround: you have to create a .NET Framework 4.6.1 Class Library project in your solution. It has a drawback: on Jenkins building and running such project is way different than .NET Core projects and your whole configuration gets bigger.

Jenkins

MS Build is also not yet integrated with .NET Core. We had to publish each app separately by command


dotnet publish

but it turned out that this command uses some external tools that you can find in “(..)\Program Files\Microsoft Visual Studio 14.0\Web\External” and are not available on a computer without Visual Studio installed. So you have to copy it and modify PATH variable by executing:


Path=%PATH%;(path to folder with VS external tools);

As for testing:


dotnet test -parallel all -xml test-result.xml

and for regular .NET Framework 4.6.1 (Selenium) we used more complicated scripts that copy XUnit binaries into project folder and then execute tests with xunit.console.exe. You can find them at “AuthServer\XUnit4JenkinsExecutorCore.bat” and “JenkinsScripts\XUnit4JenkinsExecutor.bat”.

At the end XUnit plugin showed us results of tests.

Sonar

We had to resign from Sonar – it lacks .NET Core support as well.

TempData

To use TempData we had to download “Microsoft.AspNetCore.Session” and “Microsoft.Extensions.Caching.Memory” and check whether they had proper version. Next we had to configure it in Startup:


public void ConfigureServices(IServiceCollection services)
{
    // This two methods below have to be before AddMvc()
    services.AddDistributedMemoryCache();
    services.AddSession();
 
 
    services.AddMvc();         	
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory)
{
    app.UseSession();
        	
    app.UseMvc(routes => {
        routes.MapRoute(
        name: "default",
        template: "{controller=Account}/{action=LoginPage}/{id?}");
    }); 
}

 

To sum up, our beginning with .NET Core 1.0.0 was quite challenging. A lot of frameworks which we wanted to use didn’t work or had not been released. In the Internet there were not so many posts which would help us. On the other hand there is more and more information about it every day. We think that .NET Core 1.0.0 is a great solution for the future and we are glad that we were able to learn it during the summer internship programme in Fingo.

The whole projects is open-sourced on GitHub.[:pl]

From our interns

Our names are Justyna Setlak, Szymon Matwijów and Julian Pszczołowski. We are students who did an internship in Fingo during 2016 summer holidays.

Our task was to create a server whose API one can use to authenticate and authorize users – something like login in with Facebook – and a web app to manage the server comfortably.

We were using .NET Core 1.0.0, .NET Framework 4.6.1 and Jenkins as a continuous integration tool, which was building, testing and publishing the code. It was really a surprise to us that we had to work in ASP.NET Core 1.0.0 instead of an earlier version.

This ASP.NET was really new at that time, it was released only one month before our internship. We were very keen on working in it, but also quite concerned about it. We didn’t know whether it would be very different from the earlier versions. We didn’t know whether there will be a lot of frameworks working properly. We even didn’t know if there will be posts online that would help us in our work.

Unfortunately, our fears were confirmed and we had some difficulties, especially with bringing ASP.NET Core application to life and integrating it with Jenkins. Here are details of some of the problems we encountered:

Entity Framework

Create repository pattern as Core Library project and run migrations

We wanted to have data source layer as a Core Library project to store our entities, database context and queries. But we couldn’t reference this project to our web applications and run Entity Framework migrations. We solved this problem by a small workaround.

Also, we had to use those CMD commands for migrations in nuget package manager:


cd .\DatabaseLibraryProject
dotnet ef migrations add init
dotnet ef database update

Many to many relationships

Many-to-many relationships without an entity class to represent the join table are not yet supported.

We couldn’t create many-to-many relationships without creating entity class which represented join (association) table. We had to create two separate one-to-many relationships and entity class for the join table.

Creating sample many-to-many relationship – Entity framework documentation

Autofac

We had a lot of factories (one factory – one action). We did not want to register each factory in register module. We wanted to be able to register all the factories that inherit from IActionFactory interface and are located in Fingo.Auth.Domain.*. Here is the code which enabled us to do so:


public class DomainFactoryModule : Module
{
    private const string LibrariesName = "Fingo.Auth.Domain.";

    protected override void Load(ContainerBuilder builder)
    {
        RegisterSubServices(builder);
    }

    private void RegisterSubServices(ContainerBuilder builder)
    {
        var loadableAssemblies = LoadAssemblies();

        builder.RegisterAssemblyTypes(loadableAssemblies.ToArray())
            .Where(t => t.GetInterfaces()
                .Any(i => i.IsAssignableFrom(typeof(IActionFactory))))
            .AsImplementedInterfaces()
            .InstancePerDependency();
    }

    private List<Assembly> LoadAssemblies()
    {
       var deps = DependencyContext.Default;

       return (from compilationLibrary in deps.CompileLibraries
                where compilationLibrary.Name.Contains(LibrariesName)
                select Assembly.Load(new AssemblyName(compilationLibrary.Name)))
                .ToList();
    }
}

Excel files

As of the end of August 2016, there was no framework that could help us in creating or opening .XLS and .XLSX files. Therefore we switched to simple CSV and TSV formats.

Selenium

Selenium was not available for .NET Core either, but there is a workaround: you have to create a .NET Framework 4.6.1 Class Library project in your solution. It has a drawback: on Jenkins building and running such project is way different than .NET Core projects and your whole configuration gets bigger.

Jenkins

MS Build is also not yet integrated with .NET Core. We had to publish each app separately by command


dotnet publish

but it turned out that this command uses some external tools that you can find in “(..)\Program Files\Microsoft Visual Studio 14.0\Web\External” and are not available on a computer without Visual Studio installed. So you have to copy it and modify PATH variable by executing:


Path=%PATH%;(path to folder with VS external tools);

As for testing:


dotnet test -parallel all -xml test-result.xml

and for regular .NET Framework 4.6.1 (Selenium) we used more complicated scripts that copy XUnit binaries into project folder and then execute tests with xunit.console.exe. You can find them at “AuthServer\XUnit4JenkinsExecutorCore.bat” and “JenkinsScripts\XUnit4JenkinsExecutor.bat”.

At the end XUnit plugin showed us results of tests.

Sonar

We had to resign from Sonar – it lacks .NET Core support as well.

TempData

To use TempData we had to download “Microsoft.AspNetCore.Session” and “Microsoft.Extensions.Caching.Memory” and check whether they had proper version. Next we had to configure it in Startup:


public void ConfigureServices(IServiceCollection services)
{
    // This two methods below have to be before AddMvc()
    services.AddDistributedMemoryCache();
    services.AddSession();
 
 
    services.AddMvc();         	
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory)
{
    app.UseSession();
        	
    app.UseMvc(routes => {
        routes.MapRoute(
        name: "default",
        template: "{controller=Account}/{action=LoginPage}/{id?}");
    }); 
}

 

To sum up, our beginning with .NET Core 1.0.0 was quite challenging. A lot of frameworks which we wanted to use didn’t work or had not been released. In the Internet there were not so many posts which would help us. On the other hand there is more and more information about it every day. We think that .NET Core 1.0.0 is a great solution for the future and we are glad that we were able to learn it during the summer internship programme in Fingo.

The whole projects is open-sourced on GitHub.

FINGO
About

At FINGO we promote a culture of maturity and lasting relationships. This helps us build better software and deliver value for our clients in the long run.