.Net core

.NET Core to develop console or Web applications. .NET Core is a set of runtime, library and compiler components that allow you to create apps that run on Windows, macOS and Linux.

.NET Core has the following characteristics:

These components are distributed in the following ways:

The major differences between .NET Core and the .NET Framework:

.NET Core is an open-source, general-purpose development platform maintained by Microsoft and the .NET community on GitHub. It's cross-platform (supporting Windows, macOS, and Linux) and can be used to build device, cloud, and IoT applications.

Dependency Injection is used similar to Spring.

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

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies.

A dependency is any object that another object requires.

https://dotnet.microsoft.com/download/dotnet-core/3.0

SDK 3.0.102

Dotnet core commands (dotnet core cli - command line interface) (scafolding, prepare projects).

dotnet new console
dotnet run

https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-1

In browser tutorial

Sample hello world

.
├── appSolution.sln
├── Dockerfile
├── myApp
│   ├── myApp.csproj
│   └── Program.cs
├── myLib
│   ├── Class1.cs
│   └── myLib.csproj
├── myLibTests
│   ├── myLibTests.csproj
│   └── UniTest1.cs

Dockerfile

FROM microsoft/dotnet:2.0-sdk
WORKDIR /app
RUN apt-get update
RUN apt-get install net-tools procps vim nano -y
RUN mkdir -p /app/myApp
RUN mkdir -p /app/myLib
RUN mkdir -p /app/myLibTests
ADD myApp/* /app/myApp/
ADD myLib/* /app/myLib/
ADD myLibTests/* /app/myLibTests/
ADD appSolution.sln /app/
RUN cd /app && dotnet clean && dotnet build
RUN cd /app/myLibTests && dotnet clean && dotnet test
CMD cd /app/myApp/ && dotnet bin/Debug/netcoreapp2.0/myApp.dll && tail -f /var/log/lastlog
#CMD  tail -f /var/log/lastlog

appSolution.sln

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "myApp", "myApp\myApp.csproj", "{5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "myLib", "myLib\myLib.csproj", "{00D6703F-2D64-4D9A-95AA-430DC38E4EC3}"
EndProject
Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
                Debug|x64 = Debug|x64
                Debug|x86 = Debug|x86
                Release|Any CPU = Release|Any CPU
                Release|x64 = Release|x64
                Release|x86 = Release|x86
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Debug|x64.ActiveCfg = Debug|x64
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Debug|x64.Build.0 = Debug|x64
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Debug|x86.ActiveCfg = Debug|x86
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Debug|x86.Build.0 = Debug|x86
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Release|Any CPU.Build.0 = Release|Any CPU
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Release|x64.ActiveCfg = Release|x64
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Release|x64.Build.0 = Release|x64
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Release|x86.ActiveCfg = Release|x86
                {5E009AC4-9BF5-4E1B-9C22-377AC9ECC4EB}.Release|x86.Build.0 = Release|x86
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Debug|x64.ActiveCfg = Debug|x64
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Debug|x64.Build.0 = Debug|x64
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Debug|x86.ActiveCfg = Debug|x86
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Debug|x86.Build.0 = Debug|x86
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Release|Any CPU.Build.0 = Release|Any CPU
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Release|x64.ActiveCfg = Release|x64
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Release|x64.Build.0 = Release|x64
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Release|x86.ActiveCfg = Release|x86
                {00D6703F-2D64-4D9A-95AA-430DC38E4EC3}.Release|x86.Build.0 = Release|x86
        EndGlobalSection
EndGlobal

myApp/Program.cs

   1 using System;
   2 using myLib;
   3 
   4 namespace myApp
   5 {
   6     class Program
   7     {
   8         static void Main(string[] args)
   9         {
  10             Console.WriteLine( Class1.getHelloWorld() );
  11         }
  12     }
  13 }

myApp/myApp.csproj

   1 <Project Sdk="Microsoft.NET.Sdk">
   2 
   3   <ItemGroup>
   4     <ProjectReference Include="..\myLib\myLib.csproj" />
   5   </ItemGroup>
   6 
   7   <PropertyGroup>
   8     <OutputType>Exe</OutputType>
   9     <TargetFramework>netcoreapp2.0</TargetFramework>
  10   </PropertyGroup>
  11 
  12 </Project>

myLib/Class1.cs

   1 using System;
   2 
   3 namespace myLib
   4 {
   5     public class Class1
   6     {
   7         public static String getHelloWorld()
   8         {
   9             return "Hello world from library.";
  10         }
  11     }
  12 }

myLib/myLib.csproj

   1 <Project Sdk="Microsoft.NET.Sdk">
   2 
   3   <PropertyGroup>
   4     <TargetFramework>netstandard2.0</TargetFramework>
   5   </PropertyGroup>
   6 
   7 </Project>

myLibTests/UniTest1.cs

   1 using System;
   2 using Xunit;
   3 using myLib;
   4 
   5 namespace myLibTests
   6 {
   7     public class UnitTest1
   8     {
   9         [Fact]
  10         public void Test1()
  11         {
  12             Assert.Equal("Hello world from library." , Class1.getHelloWorld() );
  13         }
  14     }
  15 }

myLibTests/myLibTests.csproj

   1 <Project Sdk="Microsoft.NET.Sdk">
   2 
   3   <PropertyGroup>
   4     <TargetFramework>netcoreapp2.0</TargetFramework>
   5 
   6     <IsPackable>false</IsPackable>
   7   </PropertyGroup>
   8 
   9   <ItemGroup>
  10     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.0" />
  11     <PackageReference Include="xunit" Version="2.3.1" />
  12     <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
  13     <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
  14   </ItemGroup>
  15 
  16   <ItemGroup>
  17     <ProjectReference Include="..\myLib\myLib.csproj" />
  18   </ItemGroup>
  19 
  20 </Project>

Docker commands

   1 #build image
   2 docker build -t dotnetcorehello .
   3 # execute bash in running container
   4 docker exec -it $1 bash
   5 # delete all containers
   6 docker ps -a | awk '//{print $1}' | grep  -v "CONTAINER" | xargs -i sh -c 'docker stop {};docker rm {}'
   7 # execute container using inage dotnetcorehello
   8 docker run -d  dotnetcorehello
   9 # list all containers
  10 docker ps -a

dotnet core commands

   1 # build solution
   2 cd /app 
   3 dotnet clean 
   4 dotnet build
   5 # run tests for library myLibTests
   6 cd /app/myLibTests 
   7 dotnet clean 
   8 dotnet test
   9 # execute app
  10 cd /app/myApp/ 
  11 dotnet bin/Debug/netcoreapp2.0/myApp.dll

test Task

   1 // buiild and run with mono
   2 // mcs testTask.cs 
   3 // mono testTask.exe 
   4 
   5 using System;
   6 using System.Threading.Tasks;
   7 using System.Threading;
   8 // string interpolation with $ might not be supported in mono
   9 
  10 namespace testTask
  11 {
  12     class Program
  13     {
  14         static void Main()
  15         {
  16             var x=1;
  17             // String interpolation $"{varxyz}"
  18             //Console.WriteLine($"ThreadId {Thread.CurrentThread.ManagedThreadId}");
  19             Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId);
  20             Task t = Task.Run( () => {
  21                 x++;
  22                 Console.WriteLine("Stuff");
  23                 //Console.WriteLine($"ThreadId {Thread.CurrentThread.ManagedThreadId}");
  24                 Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId);
  25             } );
  26             t.ContinueWith((Task task)=>{
  27                 x++;
  28                 Console.WriteLine("This the end !");
  29                 //Console.WriteLine($"ThreadId {Thread.CurrentThread.ManagedThreadId}");
  30                 Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId);
  31                 task.ContinueWith((Task t2)=>{
  32                     x++;
  33                     Console.WriteLine("t2 {0}",x);
  34                     Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId);
  35                 });
  36             });
  37             //t.Wait();  
  38             var tx = Task<long>.Run( ()=>{ return 11L; } );
  39 
  40             tx.ContinueWith((Task<long> txy)=>{
  41                 //Console.WriteLine($"Res: {txy.Result}");
  42                 Console.WriteLine("Res: {0}",txy.Result);
  43             });         
  44         }
  45     }
  46 }

test foreach

   1 //build and run using mono
   2 //mcs testForeach.cs 
   3 //mono testForeach.exe
   4 using System;
   5 using System.Collections.Generic;
   6 
   7 namespace loopNrs
   8 {
   9     class Program
  10     {
  11         static void Main()
  12         {
  13             var numbers = new List<long> { 1,2,3,4 };
  14             foreach (var nr in numbers)
  15             {
  16                 //string interpolation is not supported in mono !?
  17                 // Console.WriteLine($"Hello {nr}!");
  18                 Console.WriteLine("Hello {0}!",nr);
  19             }
  20         }
  21     }
  22 }

Sample DI (in debian buster)

Commands:

   1 dotnet build
   2 dotnet bin/Debug/netcoreapp3.1/testDI.dll

testDI.csproj

   1 <Project Sdk="Microsoft.NET.Sdk">
   2 
   3   <PropertyGroup>
   4     <OutputType>Exe</OutputType>
   5     <TargetFramework>netcoreapp3.1</TargetFramework>
   6   </PropertyGroup>
   7 
   8   <ItemGroup>
   9     <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.0" />
  10   </ItemGroup>
  11 
  12 </Project>

Program.cs

   1 using System;
   2 using Microsoft.Extensions.DependencyInjection;
   3 
   4 namespace testDI
   5 {
   6     interface IDummy : IDisposable
   7     {
   8         string GetPong();
   9     }
  10 
  11     interface ISnafu : IDisposable
  12     {
  13         string GetSnafu();
  14     }
  15     
  16     interface ITransx : IDisposable
  17     {
  18         string GetTransx();
  19     }
  20     
  21     class Transx : ITransx
  22     {
  23         private string guid;
  24         
  25         public Transx()
  26         {
  27             guid = Guid.NewGuid().ToString();
  28             Console.WriteLine($"Constructed transx {guid} !");
  29         }
  30         
  31         public string GetTransx()
  32         {
  33             return $"Transx {guid} !";
  34         }
  35         
  36         public void Dispose()
  37         {
  38             Console.WriteLine($"Disposing transx {guid} !");
  39         }        
  40     }
  41     
  42     class Dummy : IDummy
  43     {
  44         private string guid;
  45         
  46         public Dummy()
  47         {
  48             guid = Guid.NewGuid().ToString();
  49             Console.WriteLine($"Constructed dummy {guid} !");
  50         }
  51         
  52         public string GetPong()
  53         {
  54             return $"Pong {guid} !";
  55         }
  56         
  57         public void Dispose()
  58         {
  59             Console.WriteLine($"Disposing dummy {guid} !");
  60         }
  61     }
  62     
  63     class Snafu:ISnafu
  64     {
  65         private IDummy dummy;
  66         private string guid;
  67         
  68         public Snafu(IDummy dummy)
  69         {
  70             this.dummy = dummy;
  71             guid = Guid.NewGuid().ToString();
  72             Console.WriteLine($"Constructed snafu {guid} !");
  73         }
  74         
  75         public string GetSnafu()
  76         {
  77             return $"Snafu {guid} related with {dummy.GetPong() }!";
  78         }
  79         
  80         public void Dispose()
  81         {
  82             Console.WriteLine($"Disposing snafu {guid} !");
  83         }        
  84     }
  85     
  86     class Program
  87     {
  88         private static IServiceProvider ioc; //Default implementation ServiceProvider
  89         
  90         private static void PrepareContainer()
  91         {
  92             var serviceCollection = new ServiceCollection();
  93             serviceCollection.AddSingleton<IDummy, Dummy>();
  94             serviceCollection.AddSingleton<ISnafu, Snafu>();
  95             serviceCollection.AddTransient<ITransx, Transx>();
  96             ioc = serviceCollection.BuildServiceProvider();            
  97         }
  98         
  99         static void Main(string[] args)
 100         {
 101             Console.WriteLine("Hello World DI!");
 102             TestOne();
 103             TestTwo();
 104         }
 105         
 106         private static void TestOne()
 107         {
 108             Console.WriteLine("\nTestOne");
 109             PrepareContainer();
 110             var d1 = ioc.GetService<IDummy>();
 111             Console.WriteLine( $"{d1.GetPong()}" );
 112             var d2 = ioc.GetService<IDummy>();
 113             Console.WriteLine( $"{d2.GetPong()}" );
 114             var s1 = ioc.GetService<ISnafu>();
 115             Console.WriteLine($"{s1.GetSnafu()}" );
 116             var s2 = ioc.GetService<ISnafu>();
 117             Console.WriteLine($"{s2.GetSnafu()}" );            
 118             var t1 = ioc.GetService<ITransx>();
 119             Console.WriteLine($"{t1.GetTransx()}" );
 120             var t2 = ioc.GetService<ITransx>();
 121             Console.WriteLine($"{t2.GetTransx()}" );
 122             var t3 = ioc.GetService<ITransx>();
 123             Console.WriteLine($"{t3.GetTransx()}" );            
 124             ReleaseContainer();            
 125         }
 126         
 127         private static void TestTwo()
 128         {
 129             Console.WriteLine("\nTestTwo");
 130             PrepareContainer();            
 131             var sx1 = ioc.GetService<ISnafu>();
 132             Console.WriteLine($"{sx1.GetSnafu()}" );
 133             var dx1 = ioc.GetService<IDummy>();
 134             Console.WriteLine( $"{dx1.GetPong()}" );
 135             var dx2 = ioc.GetService<IDummy>();
 136             Console.WriteLine( $"{dx2.GetPong()}" );
 137             ReleaseContainer();            
 138         }
 139         
 140         private static void ReleaseContainer()
 141         {
 142             // dispose container and services in it
 143             if(ioc is IDisposable)
 144             {
 145                 Console.WriteLine("Can dispose stuff !");
 146                 ( (IDisposable)ioc).Dispose();
 147             }            
 148         }
 149     }
 150 }

Example output

Hello World DI!

TestOne
Constructed dummy 37a7cced-15c3-4b33-9eec-55f0fb58ce8c !
Pong 37a7cced-15c3-4b33-9eec-55f0fb58ce8c !
Pong 37a7cced-15c3-4b33-9eec-55f0fb58ce8c !
Constructed snafu 619160b5-6e67-4396-8555-f453bd1ad06f !
Snafu 619160b5-6e67-4396-8555-f453bd1ad06f related with Pong 37a7cced-15c3-4b33-9eec-55f0fb58ce8c !!
Snafu 619160b5-6e67-4396-8555-f453bd1ad06f related with Pong 37a7cced-15c3-4b33-9eec-55f0fb58ce8c !!
Constructed transx 6cf6600a-e622-46fd-8d10-3b6015601911 !
Transx 6cf6600a-e622-46fd-8d10-3b6015601911 !
Constructed transx c666091c-efe9-407f-8659-6c1bdc7e2b7f !
Transx c666091c-efe9-407f-8659-6c1bdc7e2b7f !
Constructed transx 421a63ca-0e93-4656-ba5c-c8909774827c !
Transx 421a63ca-0e93-4656-ba5c-c8909774827c !
Can dispose stuff !
Disposing transx 421a63ca-0e93-4656-ba5c-c8909774827c !
Disposing transx c666091c-efe9-407f-8659-6c1bdc7e2b7f !
Disposing transx 6cf6600a-e622-46fd-8d10-3b6015601911 !
Disposing snafu 619160b5-6e67-4396-8555-f453bd1ad06f !
Disposing dummy 37a7cced-15c3-4b33-9eec-55f0fb58ce8c !

TestTwo
Constructed dummy 7233afd9-9f2e-43a4-ae1a-bc0abba6abc7 !
Constructed snafu 10298883-4f16-4383-b5b7-ce9e5ad90715 !
Snafu 10298883-4f16-4383-b5b7-ce9e5ad90715 related with Pong 7233afd9-9f2e-43a4-ae1a-bc0abba6abc7 !!
Pong 7233afd9-9f2e-43a4-ae1a-bc0abba6abc7 !
Pong 7233afd9-9f2e-43a4-ae1a-bc0abba6abc7 !
Can dispose stuff !
Disposing snafu 10298883-4f16-4383-b5b7-ce9e5ad90715 !
Disposing dummy 7233afd9-9f2e-43a4-ae1a-bc0abba6abc7 !

Eager service bean instantiation

To instantiate a service/bean before being used else where add it as an argument in the Configure method that belongs to the Startup class.

RBAC role based authorization

Identity is enabled for the application by calling UseAuthentication in the Configure method. Startup.cs in dotnet core to init the services/beans.

In ASP.NET Core MVC, views are .cshtml files that use the C# programming language in Razor markup.

@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<p>Use this area to provide additional information.</p>

   1 // method About related with About.cshtml
   2 // ViewData["Message"] defined in the method and accessed inside the view in the About.cshtml
   3 public IActionResult About()
   4 {
   5     ViewData["Message"] = "Your application description page.";
   6 
   7     return View();
   8     // return explicit view Orders
   9     // return View("Orders");
  10     // return both a view and a model
  11     // return View("Orders", Orders);
  12 }

View discovery searches for a matching view file in this order:

Pass data to views using several approaches:

Strong type sample

// CSHTML
@model WebApplication1.ViewModels.Address

<h2>Contact</h2>
<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>
To provide the model to the view, the controller passes it as a parameter:

// C#
public IActionResult Contact()
{
    ViewData["Message"] = "Your contact page.";

    var viewModel = new Address()
    {
        Name = "Microsoft",
        Street = "One Microsoft Way",
        City = "Redmond",
        State = "WA",
        PostalCode = "98052-6399"
    };

    return View(viewModel);
}

Angular automatically passes an antiforgery token in a request header named X-XSRF-TOKEN. The ASP.NET Core MVC app is configured to refer to this header in its configuration in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    // Angular's default header name for sending the XSRF token.
    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

    services.AddMvc();
}

Install dotnetcore in CentOS

   1 rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
   2 yum install dotnet-sdk-2.2
   3 dotnet new console --name hello-console
   4 yum install epel-release
   5 yum install nodejs
   6 dotnet new reactredux --name "react-test"
   7 cd react-test/
   8 dotnet clean
   9 dotnet build
  10 dotnet publish
  11 dotnet  bin/Debug/netcoreapp2.2/publish/react-test.dll
  12 vi Program.cs

   1 using System;
   2 using System.Collections.Generic;
   3 using System.IO;
   4 using System.Linq;
   5 using System.Threading.Tasks;
   6 using Microsoft.AspNetCore;
   7 using Microsoft.AspNetCore.Hosting;
   8 using Microsoft.Extensions.Configuration;
   9 using Microsoft.Extensions.Logging;
  10 
  11 namespace react_test
  12 {
  13     public class Program
  14     {
  15         public static void Main(string[] args)
  16         {
  17             CreateWebHostBuilder(args).Build().Run();
  18         }
  19 
  20         public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
  21             WebHost.CreateDefaultBuilder(args)
  22                 .UseStartup<Startup>().UseUrls("http://0.0.0.0:5000;https://0.0.0.0:5001");
  23     }
  24 }

Kestrel

Kestrel is a cross-platform web server for ASP.NET Core. Kestrel is the web server that's included by default in ASP.NET Core project templates.

Kestrel supports the following scenarios:

Install dotnetcore in Debian buster

   1 wget https://packages.microsoft.com/config/ubuntu/19.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
   2 sudo dpkg -i packages-microsoft-prod.deb
   3 sudo apt-get update
   4 sudo apt-get install apt-transport-https
   5 sudo apt-get update
   6 sudo apt-get install dotnet-sdk-3.1 nodejs npm dotnet-sdk-2.1
   7 # https://code.visualstudio.com/
   8 cd ~/Downloads
   9 wget https://go.microsoft.com/fwlink/?LinkID=760868
  10 mv index.html\?LinkID\=760868 vscode.deb
  11 sudo dpkg -i vscode.deb # 1.43.2
  12 code &
  13 # Install extension ms-dotnettools.csharp
  14 # Install extension Eclipse Keymap alphabotsec.vscode-eclipse-keybindings
  15 

Angular project

   1 # nodejs --version # v12.16.2
   2 # npm --version # 6.14.4
   3 # dotnet --version # 3.1.201
   4 cd ~
   5 dotnet new angular --name test # creates folder test with the project 
   6 cd test
   7 dotnet clean 
   8 dotnet build 
   9 dotnet run 
  10 https://localhost:5001/
  11 # There are issues building the project on the sandbox folder shared with windows through a mounted folder.
  12 

ILspy

Install MSSQL server 2017 express in Debian Linux buster

   1 sudo apt-get install apt-transport-https
   2 curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
   3 curl https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2017.list | sudo tee /etc/apt/sources.list.d/mssql-server.list
   4 sudo apt update
   5 # deb http://ftp.debian.org/debian jessie main
   6 echo "deb http://ftp.debian.org/debian jessie main" >>  /etc/apt/sources.list
   7 sudo apt update
   8 sudo apt-get install libssl1.0
   9 sudo apt-get install mssql-server
  10 sudo systemctl restart mssql-server.service
  11 sudo /opt/mssql/bin/mssql-conf setup
  12 # "Express" edition is free to use with limitations.
  13 # Choose 3) Express (free)
  14 # Enter the SQL Server system administrator password: **********
  15 # The licensing PID was successfully processed. The new edition is [Express Edition].
  16 # install sqlcmd
  17 sudo apt install mssql-tools
  18 nano ~/.bashrc
  19 PATH=$PATH:/opt/mssql-tools/bin/
  20 . ~/.bashrc # reload .bashrc
  21 # tcp6       0      0 :::1433                 :::*                    LISTEN
  22 
  23 sqlcmd -S localhost -U sa -P ********
  24 # 1> exec sp_databases
  25 # 2> go
  26 # https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility?view=sql-server-ver15
  27 # select name from sys.databases
  28 # go
  29 # exit
  30 # example connection string 
  31 #   Data Source=LOCALHOST;Initial Catalog=TestDB;User Id=sa;Password=********;App=TestApp
  32 

Swagger

   1 dotnet new webapi --name test-webapi
   2 dotnet add test.csproj package Swashbuckle.AspNetCore
   3 dotnet build
   4 dotnet run
   5 # https://localhost:5001/swagger/index.html 
   6 curl -X GET "https://localhost:5001/WeatherForecast" -H  "accept: text/plain" -k

   1 using Microsoft.OpenApi.Models;
   2 /* in Startup.cs ConfigureServices */
   3 services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });  });
   4 /* in Startup,cs Configure */
   5 app.UseSwagger();
   6 app.UseSwaggerUI(c =>  { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");     });

Multiple file upload controller example

   1 using System;
   2 using System.Collections.Generic;
   3 using System.IO;
   4 using System.Text;
   5 using System.Threading;
   6 using System.Threading.Tasks;
   7 using Microsoft.AspNetCore.Http;
   8 using Microsoft.AspNetCore.Mvc;
   9 using Microsoft.Extensions.Logging;
  10 
  11 namespace test_webapi.Controllers
  12 {
  13     [ApiController]
  14     [Route("[controller]")]
  15     public class UploadController : ControllerBase
  16     {
  17         private readonly ILogger<UploadController> _logger;
  18 
  19         public UploadController(ILogger<UploadController> logger)
  20         {
  21             _logger = logger;
  22         }
  23 
  24         //---
  25         private void ShowHeadersConsole()
  26         {
  27             Console.WriteLine($"Headers");
  28             foreach (var h in Request.Headers)
  29             {
  30                 Console.WriteLine($"{h.Key}:{h.Value}");
  31             }
  32         }
  33 
  34         private async void ShowFormDataConsole()
  35         {
  36             Task<IFormCollection> task = Request.ReadFormAsync(CancellationToken.None);
  37 
  38             await task;
  39 
  40             Console.WriteLine($"Form stuff ...");
  41             // an uploaded file will not be shown  !
  42             foreach (var formItem in task.Result)
  43             {
  44                 Console.WriteLine($"{formItem.Key}:{formItem.Value}");
  45             }
  46         }
  47 
  48         private void ShowBodyConsole()
  49         {
  50             Console.WriteLine("Body");
  51             using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
  52             {
  53                 Task<string> t = reader.ReadToEndAsync();
  54                 // await t;
  55                 t.Wait();
  56                 Console.WriteLine(t.Result);
  57             }
  58         }
  59 
  60         public class FormPayload1
  61         {
  62             public IFormFile UploadedFile1 { get; set; }
  63             public IFormFile UploadedFile2 { get; set; }
  64             public IFormFile UploadedFile3 { get; set; }
  65             public IFormFile UploadedFile4 { get; set; }
  66             public IFormFile UploadedFile5 { get; set; }
  67             public IFormFile UploadedFile6 { get; set; }
  68             public IFormFile UploadedFile7 { get; set; }
  69             public IFormFile UploadedFile8 { get; set; }
  70             public IFormFile UploadedFile9 { get; set; }
  71 
  72             public string TestName { get; set; }
  73         }
  74 
  75         public class FormPayload2
  76         {
  77             public IFormFileCollection UploadedFiles { get; set; }
  78             public string TestName { get; set; }
  79         }
  80 
  81         [HttpPost]
  82         [Route("[controller]/[action]")]
  83         public async Task<IActionResult> FilesApproach1([FromForm] FormPayload1 payload)
  84         {
  85             var millisSinceDawnTime = DateTime.Now.Ticks / 10000;
  86 
  87             ShowHeadersConsole();
  88             ShowFormDataConsole();
  89             ShowBodyConsole();
  90             List<string> paths = new List<string>();
  91 
  92             Console.WriteLine($"Test name: {payload.TestName} ");
  93 
  94             // identify uploaded files properties that have data and create asynch tasks to get that data
  95             List<Task<string>> tasks = new List<Task<string>>();
  96             foreach (var pi in payload.GetType().GetProperties())
  97             {
  98                 if (pi.GetValue(payload) != null && pi.Name.StartsWith("UploadedFile"))
  99                 {
 100                     Task<string> task = this.HandleFile((IFormFile)pi.GetValue(payload));
 101                     tasks.Add(task);
 102                 }
 103             }
 104 
 105             await Task.WhenAll(tasks);
 106             foreach (var task in tasks)
 107             {
 108                 paths.Add(task.Result);
 109             }
 110 
 111             return Ok(new { storePaths = paths });
 112         }
 113 
 114         [HttpPost]
 115         [Route("[controller]/[action]")]
 116         public async Task<IActionResult> FilesApproach2([FromForm] FormPayload2 payload)
 117         {
 118             /*
 119             Repeat the field uploadedFiles per file to upload
 120             curl -v -X POST -F 'UploadedFiles=@/home/vitor/test.png' -F 'UploadedFiles=@/home/vitor/Vitor.png' -F 'TestName=namex' -k https://localhost:5001/Upload/Upload/FilesApproach2
 121             */
 122             var millisSinceDawnTime = DateTime.Now.Ticks / 10000;
 123 
 124             ShowHeadersConsole();
 125             ShowFormDataConsole();
 126             ShowBodyConsole();
 127             List<string> paths = new List<string>();
 128             List<Task<string>> tasks = new List<Task<string>>();
 129 
 130             Console.WriteLine($"Test name: {payload.TestName} ");
 131             Console.WriteLine($"Amount files: {payload.UploadedFiles.Count} ");
 132 
 133             foreach (var f in payload.UploadedFiles)
 134             {
 135                 Task<string> task = this.HandleFile(f);
 136                 tasks.Add(task);
 137             }
 138 
 139             await Task.WhenAll(tasks);
 140             foreach (var t in tasks)
 141             {
 142                 paths.Add(t.Result);
 143             }
 144 
 145             return Ok(new { storePaths = paths });
 146         }
 147 
 148         private async Task<string> HandleFile(IFormFile filename)
 149         {
 150             var millisSinceDawnTime = DateTime.Now.Ticks / 10000;
 151             var filePath = String.Empty;
 152             if (filename != null)
 153             {
 154                 if (filename.Length > 0)
 155                 {
 156                     filePath = $"{Path.GetTempPath()}{millisSinceDawnTime}_{filename.FileName}";
 157                     Console.WriteLine($"Name: {filename.Name} ");
 158                     Console.WriteLine($"Filename: {filename.FileName} ");
 159                     Console.WriteLine($"Length: {filename.Length} ");
 160                     Console.WriteLine($"Type: {filename.ContentType} ");
 161                     Console.WriteLine($"Disposition: {filename.ContentDisposition} ");
 162                     Console.WriteLine($"File will be stored in: {filePath} ");
 163                     using (var stream = new FileStream(filePath, FileMode.Create))
 164                     {
 165                         await filename.CopyToAsync(stream, CancellationToken.None);
 166                     }
 167                 }
 168             }
 169 
 170             return filePath;
 171 
 172         }
 173     }
 174 }

Setup test project

   1 dotnet new mstest --name test-proj
   2 cd test-proj/
   3 //UnitTest1.cs
   4 using FluentAssertions;
   5 using Microsoft.VisualStudio.TestTools.UnitTesting; // MSTest 
   6 using Moq;
   7 
   8 dotnet add package Moq --version 4.14.1
   9 dotnet add package Microsoft.Extensions.Logging --version 3.1.4
  10 dotnet add package FluentAssertions --version 5.10.3
  11 dotnet add reference ../other-proj.csproj
  12 dotnet add package Microsoft.EntityFrameworkCore.Sqlite

EF core test - sqlite

   1 // dotnet add package Microsoft.EntityFrameworkCore.Sqlite
   2 var context = new MyDbContext(new DbContextOptionsBuilder<MyDbContext>().UseSqlite(CreateInMemoryDatabase()).Options);
   3 
   4         private static DbConnection CreateInMemoryDatabase()
   5         {
   6             var connection = new SqliteConnection("Filename=:memory:");
   7             connection.Open();
   8             return connection;
   9         }
  10 
  11 
  12 
  13 using System;
  14 using System.Data.Common;
  15 using FluentAssertions;
  16 using Microsoft.Data.Sqlite;
  17 using Microsoft.EntityFrameworkCore;
  18 using Microsoft.Extensions.Logging;
  19 using Microsoft.VisualStudio.TestTools.UnitTesting;
  20 using Moq;
  21 using test_webapi_efcore.Controllers;
  22 using test_webapi_efcore.Domain;
  23 using test_webapi_efcore.Persistence;
  24 
  25 namespace test_webapi_efcore.UnitTests
  26 {
  27     [TestClass]
  28     public class ControllerTest
  29     {
  30       [TestMethod]
  31        public void Create_IsOkay()
  32        {
  33        }
  34    }
  35 }

CSharp/dotnetcore (last edited 2023-05-26 14:06:22 by 127)