<> = .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. * https://docs.microsoft.com/en-us/dotnet/core/about .NET Core has the following characteristics: * Cross-platform: Runs on Windows, macOS, and Linux operating systems. * Consistent across architectures: Runs your code with the same behavior on multiple architectures, including x64, x86, and ARM. * Command-line tools: Includes easy-to-use command-line tools that can be used for local development and in continuous-integration scenarios. * Flexible deployment: Can be included in your app or installed side-by-side (user-wide or system-wide installations). Can be used with Docker containers. * Compatible: .NET Core is compatible with .NET Framework, Xamarin, and Mono, via .NET Standard. * Open source: The .NET Core platform is '''open source, using MIT and Apache 2 licenses'''. .NET Core is a .NET Foundation project. * Supported by Microsoft: .NET Core is supported by Microsoft, per .NET Core Support. * Supported languages: C#, Visual Basic, and F# languages can be used to write applications and libraries for .NET Core. These components are distributed in the following ways: * .NET Core Runtime -- includes the .NET Core runtime and framework libraries. * ASP.NET Core Runtime -- includes ASP.NET Core and .NET Core runtime and framework libraries. * .NET Core SDK -- includes the .NET Core CLI, ASP.NET Core runtime, and .NET Core runtime and framework. The major differences between .NET Core and the .NET Framework: * App-models -- .NET Core doesn't support all the .NET Framework app-models. In particular, it doesn't support ASP.NET Web Forms and ASP.NET MVC, but it supports ASP.NET Core MVC. And starting with .NET Core 3.0, .NET Core also supports WPF and Windows Forms on Windows only. * APIs -- .NET Core contains a large subset of .NET Framework Base Class Library, with a different factoring (assembly names are different; members exposed on types differ in key cases). In some cases, these differences require changes to port source to .NET Core. For more information, see The .NET Portability Analyzer. .NET Core implements the .NET Standard API specification. * Subsystems -- .NET Core implements a subset of the subsystems in the .NET Framework, with the goal of a simpler implementation and programming model. For example, Code Access Security (CAS) isn't supported, while reflection is supported. * Platforms -- The .NET Framework supports Windows and Windows Server while .NET Core also supports macOS and Linux. * Open Source -- .NET Core is open source, while a read-only subset of the .NET Framework is open source. * https://www.microsoft.com/net/learn/get-started/windows * https://en.wikipedia.org/wiki/ASP.NET_Core * https://hub.docker.com/r/microsoft/dotnet/ * https://docs.microsoft.com/pt-pt/dotnet/core/docker/building-net-docker-images * https://msdn.microsoft.com/en-us/library/ff361664(v=vs.110).aspx * https://docs.microsoft.com/en-us/dotnet/core/ .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 * Visual Studio support: Visual Studio 2019 (v16.3 or later) * Included runtimes * .NET Core Runtime 3.0.2 (The .NET Core Runtime contains just the components needed to run a console app.) * ASP.NET Core Runtime 3.0.2 (ASP.NET Core Runtime enables you to run existing web/server applications.) * Desktop Runtime 3.0.2 (run existing Windows desktop applications.) * Language support C# 8.0 F# 4.7 * OS: Linux macOS Windows 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 * https://www.microsoft.com/net/learn/in-browser-tutorial/1 == 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 === {{{#!highlight csharp using System; using myLib; namespace myApp { class Program { static void Main(string[] args) { Console.WriteLine( Class1.getHelloWorld() ); } } } }}} === myApp/myApp.csproj === {{{#!highlight xml Exe netcoreapp2.0 }}} === myLib/Class1.cs === {{{#!highlight csharp using System; namespace myLib { public class Class1 { public static String getHelloWorld() { return "Hello world from library."; } } } }}} === myLib/myLib.csproj === {{{#!highlight xml netstandard2.0 }}} === myLibTests/UniTest1.cs === {{{#!highlight csharp using System; using Xunit; using myLib; namespace myLibTests { public class UnitTest1 { [Fact] public void Test1() { Assert.Equal("Hello world from library." , Class1.getHelloWorld() ); } } } }}} === myLibTests/myLibTests.csproj === {{{#!highlight xml netcoreapp2.0 false }}} === Docker commands === {{{#!highlight bash #build image docker build -t dotnetcorehello . # execute bash in running container docker exec -it $1 bash # delete all containers docker ps -a | awk '//{print $1}' | grep -v "CONTAINER" | xargs -i sh -c 'docker stop {};docker rm {}' # execute container using inage dotnetcorehello docker run -d dotnetcorehello # list all containers docker ps -a }}} === dotnet core commands === {{{#!highlight bash # build solution cd /app dotnet clean dotnet build # run tests for library myLibTests cd /app/myLibTests dotnet clean dotnet test # execute app cd /app/myApp/ dotnet bin/Debug/netcoreapp2.0/myApp.dll }}} == test Task == {{{#!highlight csharp // buiild and run with mono // mcs testTask.cs // mono testTask.exe using System; using System.Threading.Tasks; using System.Threading; // string interpolation with $ might not be supported in mono namespace testTask { class Program { static void Main() { var x=1; // String interpolation $"{varxyz}" //Console.WriteLine($"ThreadId {Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId); Task t = Task.Run( () => { x++; Console.WriteLine("Stuff"); //Console.WriteLine($"ThreadId {Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId); } ); t.ContinueWith((Task task)=>{ x++; Console.WriteLine("This the end !"); //Console.WriteLine($"ThreadId {Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId); task.ContinueWith((Task t2)=>{ x++; Console.WriteLine("t2 {0}",x); Console.WriteLine("ThreadId {0}",Thread.CurrentThread.ManagedThreadId); }); }); //t.Wait(); var tx = Task.Run( ()=>{ return 11L; } ); tx.ContinueWith((Task txy)=>{ //Console.WriteLine($"Res: {txy.Result}"); Console.WriteLine("Res: {0}",txy.Result); }); } } } }}} == test foreach == {{{#!highlight csharp //build and run using mono //mcs testForeach.cs //mono testForeach.exe using System; using System.Collections.Generic; namespace loopNrs { class Program { static void Main() { var numbers = new List { 1,2,3,4 }; foreach (var nr in numbers) { //string interpolation is not supported in mono !? // Console.WriteLine($"Hello {nr}!"); Console.WriteLine("Hello {0}!",nr); } } } } }}} == Sample DI (in debian buster) == Commands: {{{#!highlight sh dotnet build dotnet bin/Debug/netcoreapp3.1/testDI.dll }}} === testDI.csproj === {{{#!highlight xml Exe netcoreapp3.1 }}} === Program.cs === {{{#!highlight csharp using System; using Microsoft.Extensions.DependencyInjection; namespace testDI { interface IDummy : IDisposable { string GetPong(); } interface ISnafu : IDisposable { string GetSnafu(); } interface ITransx : IDisposable { string GetTransx(); } class Transx : ITransx { private string guid; public Transx() { guid = Guid.NewGuid().ToString(); Console.WriteLine($"Constructed transx {guid} !"); } public string GetTransx() { return $"Transx {guid} !"; } public void Dispose() { Console.WriteLine($"Disposing transx {guid} !"); } } class Dummy : IDummy { private string guid; public Dummy() { guid = Guid.NewGuid().ToString(); Console.WriteLine($"Constructed dummy {guid} !"); } public string GetPong() { return $"Pong {guid} !"; } public void Dispose() { Console.WriteLine($"Disposing dummy {guid} !"); } } class Snafu:ISnafu { private IDummy dummy; private string guid; public Snafu(IDummy dummy) { this.dummy = dummy; guid = Guid.NewGuid().ToString(); Console.WriteLine($"Constructed snafu {guid} !"); } public string GetSnafu() { return $"Snafu {guid} related with {dummy.GetPong() }!"; } public void Dispose() { Console.WriteLine($"Disposing snafu {guid} !"); } } class Program { private static IServiceProvider ioc; //Default implementation ServiceProvider private static void PrepareContainer() { var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddTransient(); ioc = serviceCollection.BuildServiceProvider(); } static void Main(string[] args) { Console.WriteLine("Hello World DI!"); TestOne(); TestTwo(); } private static void TestOne() { Console.WriteLine("\nTestOne"); PrepareContainer(); var d1 = ioc.GetService(); Console.WriteLine( $"{d1.GetPong()}" ); var d2 = ioc.GetService(); Console.WriteLine( $"{d2.GetPong()}" ); var s1 = ioc.GetService(); Console.WriteLine($"{s1.GetSnafu()}" ); var s2 = ioc.GetService(); Console.WriteLine($"{s2.GetSnafu()}" ); var t1 = ioc.GetService(); Console.WriteLine($"{t1.GetTransx()}" ); var t2 = ioc.GetService(); Console.WriteLine($"{t2.GetTransx()}" ); var t3 = ioc.GetService(); Console.WriteLine($"{t3.GetTransx()}" ); ReleaseContainer(); } private static void TestTwo() { Console.WriteLine("\nTestTwo"); PrepareContainer(); var sx1 = ioc.GetService(); Console.WriteLine($"{sx1.GetSnafu()}" ); var dx1 = ioc.GetService(); Console.WriteLine( $"{dx1.GetPong()}" ); var dx2 = ioc.GetService(); Console.WriteLine( $"{dx2.GetPong()}" ); ReleaseContainer(); } private static void ReleaseContainer() { // dispose container and services in it if(ioc is IDisposable) { Console.WriteLine("Can dispose stuff !"); ( (IDisposable)ioc).Dispose(); } } } } }}} === 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 == * https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.0&tabs=visual-studio%2Caspnetcore2x * https://docs.microsoft.com/en-us/aspnet/core/security/authorization/secure-data?view=aspnetcore-2.0 * https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.0 * https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-2.0 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. * About.cshtml {{{#!highlight csharp @{ ViewData["Title"] = "About"; }

@ViewData["Title"].

@ViewData["Message"]

Use this area to provide additional information.

}}} * HomeController.cs {{{#!highlight csharp // method About related with About.cshtml // ViewData["Message"] defined in the method and accessed inside the view in the About.cshtml public IActionResult About() { ViewData["Message"] = "Your application description page."; return View(); // return explicit view Orders // return View("Orders"); // return both a view and a model // return View("Orders", Orders); } }}} View discovery searches for a matching view file in this order: * Views/[ControllerName]/[ViewName].cshtml * Views/Shared/[ViewName].cshtml Pass data to views using several approaches: * Strongly-typed data: viewmodel * Weakly-typed data * ViewData (ViewDataAttribute) * ViewBag Strong type sample {{{#!highlight csharp // CSHTML @model WebApplication1.ViewModels.Address

Contact

@Model.Street
@Model.City, @Model.State @Model.PostalCode
P: 425.555.0100
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: {{{#!highlight csharp 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 == {{{#!highlight sh rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm yum install dotnet-sdk-2.2 dotnet new console --name hello-console yum install epel-release yum install nodejs dotnet new reactredux --name "react-test" cd react-test/ dotnet clean dotnet build dotnet publish dotnet bin/Debug/netcoreapp2.2/publish/react-test.dll vi Program.cs }}} {{{#!highlight csharp using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace react_test { public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup().UseUrls("http://0.0.0.0:5000;https://0.0.0.0:5001"); } } }}} == Kestrel == * https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1 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: * HTTPS * Opaque upgrade used to enable WebSockets * Unix sockets for high performance behind Nginx * HTTP/2 (except on macOS†) == Install dotnetcore in Debian buster == {{{#!highlight sh wget https://packages.microsoft.com/config/ubuntu/19.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb sudo apt-get update sudo apt-get install apt-transport-https sudo apt-get update sudo apt-get install dotnet-sdk-3.1 nodejs npm dotnet-sdk-2.1 # https://code.visualstudio.com/ cd ~/Downloads wget https://go.microsoft.com/fwlink/?LinkID=760868 mv index.html\?LinkID\=760868 vscode.deb sudo dpkg -i vscode.deb # 1.43.2 code & # Install extension ms-dotnettools.csharp # Install extension Eclipse Keymap alphabotsec.vscode-eclipse-keybindings }}} === Angular project === {{{#!highlight bash # nodejs --version # v12.16.2 # npm --version # 6.14.4 # dotnet --version # 3.1.201 cd ~ dotnet new angular --name test # creates folder test with the project cd test dotnet clean dotnet build dotnet run https://localhost:5001/ # There are issues building the project on the sandbox folder shared with windows through a mounted folder. }}} == ILspy == * https://github.com/icsharpcode/ILSpy open-source .NET assembly browser and decompiler. == Install MSSQL server 2017 express in Debian Linux buster == * https://dev.to/nabbisen/microsoft-sql-server-2017-on-debian-n77 {{{#!highlight bash sudo apt-get install apt-transport-https curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - curl https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2017.list | sudo tee /etc/apt/sources.list.d/mssql-server.list sudo apt update # deb http://ftp.debian.org/debian jessie main echo "deb http://ftp.debian.org/debian jessie main" >> /etc/apt/sources.list sudo apt update sudo apt-get install libssl1.0 sudo apt-get install mssql-server sudo systemctl restart mssql-server.service sudo /opt/mssql/bin/mssql-conf setup # "Express" edition is free to use with limitations. # Choose 3) Express (free) # Enter the SQL Server system administrator password: ********** # The licensing PID was successfully processed. The new edition is [Express Edition]. # install sqlcmd sudo apt install mssql-tools nano ~/.bashrc PATH=$PATH:/opt/mssql-tools/bin/ . ~/.bashrc # reload .bashrc # tcp6 0 0 :::1433 :::* LISTEN sqlcmd -S localhost -U sa -P ******** # 1> exec sp_databases # 2> go # https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility?view=sql-server-ver15 # select name from sys.databases # go # exit # example connection string # Data Source=LOCALHOST;Initial Catalog=TestDB;User Id=sa;Password=********;App=TestApp }}} == Webapi/Swagger == * https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-3.1&tabs=netcore-cli {{{#!highlight sh dotnet new webapi --name test-webapi dotnet add test.csproj package Swashbuckle.AspNetCore dotnet build dotnet run # https://localhost:5001/swagger/index.html curl -X GET "https://localhost:5001/WeatherForecast" -H "accept: text/plain" -k }}} {{{#!highlight csharp using Microsoft.OpenApi.Models; /* in Startup.cs ConfigureServices */ services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); /* in Startup,cs Configure */ app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); }}} == Multiple file upload controller example == {{{#!highlight csharp using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace test_webapi.Controllers { [ApiController] [Route("[controller]")] public class UploadController : ControllerBase { private readonly ILogger _logger; public UploadController(ILogger logger) { _logger = logger; } //--- private void ShowHeadersConsole() { Console.WriteLine($"Headers"); foreach (var h in Request.Headers) { Console.WriteLine($"{h.Key}:{h.Value}"); } } private async void ShowFormDataConsole() { Task task = Request.ReadFormAsync(CancellationToken.None); await task; Console.WriteLine($"Form stuff ..."); // an uploaded file will not be shown ! foreach (var formItem in task.Result) { Console.WriteLine($"{formItem.Key}:{formItem.Value}"); } } private void ShowBodyConsole() { Console.WriteLine("Body"); using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8)) { Task t = reader.ReadToEndAsync(); // await t; t.Wait(); Console.WriteLine(t.Result); } } public class FormPayload1 { public IFormFile UploadedFile1 { get; set; } public IFormFile UploadedFile2 { get; set; } public IFormFile UploadedFile3 { get; set; } public IFormFile UploadedFile4 { get; set; } public IFormFile UploadedFile5 { get; set; } public IFormFile UploadedFile6 { get; set; } public IFormFile UploadedFile7 { get; set; } public IFormFile UploadedFile8 { get; set; } public IFormFile UploadedFile9 { get; set; } public string TestName { get; set; } } public class FormPayload2 { public IFormFileCollection UploadedFiles { get; set; } public string TestName { get; set; } } [HttpPost] [Route("[controller]/[action]")] public async Task FilesApproach1([FromForm] FormPayload1 payload) { var millisSinceDawnTime = DateTime.Now.Ticks / 10000; ShowHeadersConsole(); ShowFormDataConsole(); ShowBodyConsole(); List paths = new List(); Console.WriteLine($"Test name: {payload.TestName} "); // identify uploaded files properties that have data and create asynch tasks to get that data List> tasks = new List>(); foreach (var pi in payload.GetType().GetProperties()) { if (pi.GetValue(payload) != null && pi.Name.StartsWith("UploadedFile")) { Task task = this.HandleFile((IFormFile)pi.GetValue(payload)); tasks.Add(task); } } await Task.WhenAll(tasks); foreach (var task in tasks) { paths.Add(task.Result); } return Ok(new { storePaths = paths }); } [HttpPost] [Route("[controller]/[action]")] public async Task FilesApproach2([FromForm] FormPayload2 payload) { /* Repeat the field uploadedFiles per file to upload 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 */ var millisSinceDawnTime = DateTime.Now.Ticks / 10000; ShowHeadersConsole(); ShowFormDataConsole(); ShowBodyConsole(); List paths = new List(); List> tasks = new List>(); Console.WriteLine($"Test name: {payload.TestName} "); Console.WriteLine($"Amount files: {payload.UploadedFiles.Count} "); foreach (var f in payload.UploadedFiles) { Task task = this.HandleFile(f); tasks.Add(task); } await Task.WhenAll(tasks); foreach (var t in tasks) { paths.Add(t.Result); } return Ok(new { storePaths = paths }); } private async Task HandleFile(IFormFile filename) { var millisSinceDawnTime = DateTime.Now.Ticks / 10000; var filePath = String.Empty; if (filename != null) { if (filename.Length > 0) { filePath = $"{Path.GetTempPath()}{millisSinceDawnTime}_{filename.FileName}"; Console.WriteLine($"Name: {filename.Name} "); Console.WriteLine($"Filename: {filename.FileName} "); Console.WriteLine($"Length: {filename.Length} "); Console.WriteLine($"Type: {filename.ContentType} "); Console.WriteLine($"Disposition: {filename.ContentDisposition} "); Console.WriteLine($"File will be stored in: {filePath} "); using (var stream = new FileStream(filePath, FileMode.Create)) { await filename.CopyToAsync(stream, CancellationToken.None); } } } return filePath; } } } }}} == Setup test project == {{{#!highlight csharp dotnet new mstest --name test-proj cd test-proj/ //UnitTest1.cs using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; // MSTest using Moq; dotnet add package Moq --version 4.14.1 dotnet add package Microsoft.Extensions.Logging --version 3.1.4 dotnet add package FluentAssertions --version 5.10.3 dotnet add reference ../other-proj.csproj dotnet add package Microsoft.EntityFrameworkCore.Sqlite }}} == EF core test - sqlite == {{{#!highlight csharp // dotnet add package Microsoft.EntityFrameworkCore.Sqlite var context = new MyDbContext(new DbContextOptionsBuilder().UseSqlite(CreateInMemoryDatabase()).Options); private static DbConnection CreateInMemoryDatabase() { var connection = new SqliteConnection("Filename=:memory:"); connection.Open(); return connection; } using System; using System.Data.Common; using FluentAssertions; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using test_webapi_efcore.Controllers; using test_webapi_efcore.Domain; using test_webapi_efcore.Persistence; namespace test_webapi_efcore.UnitTests { [TestClass] public class ControllerTest { [TestMethod] public void Create_IsOkay() { } } } }}} == Dotnet core 9 podman == === Dockerfile === {{{#!highlight sh FROM mcr.microsoft.com/dotnet/sdk:9.0 WORKDIR /app RUN apt-get update RUN apt-get install net-tools procps vim nano -y CMD tail -f /var/log/lastlog }}} === Steps === {{{#!highlight sh podman build -t dotnet9-image . podman run -d -P --name dotnet9-image-container dotnet9-image podman ps -l podman exec -it dotnet9-image-container bash cat /etc/os-release PRETTY_NAME="Debian GNU/Linux 12 (bookworm)" dotnet --version # 9.0.200 cd /app dotnet new console dotnet run dotnet bin/Debug/net9.0/app.dll # Hello, World! cat Program.cs #var hello="Hello world!"; #Console.WriteLine(hello); dotnet build dotnet bin/Debug/net9.0/app.dll # Hello world! }}} * https://builds.dotnet.microsoft.com/dotnet/Sdk/9.0.200/dotnet-sdk-9.0.200-linux-x64.tar.gz * Included runtimes * .NET Runtime 9.0.2 * ASP.NET Core Runtime 9.0.2 * .NET Desktop Runtime 9.0.2 * Language support * C# 13.0 * F# 9.0 * Visual Basic 17.13 == Install on debian 12 - bookworm / debian 11 - bullseye == {{{#!highlight sh cd ~ wget https://builds.dotnet.microsoft.com/dotnet/Sdk/9.0.200/dotnet-sdk-9.0.200-linux-x64.tar.gz mkdir ~/dotnetcore9 mv dotnet-sdk-9.0.200-linux-x64.tar.gz ~/dotnetcore9/ cd ~/dotnetcore9/ tar xvzf dotnet-sdk-9.0.200-linux-x64.tar.gz echo 'PATH="$HOME/dotnetcore9:$PATH"' >> ~/.bashrc source ~/.bashrc dotnet --version dotnet new list }}} == dotnet core 9 hello world == === Program.cs === {{{#!highlight csharp /** dotnet new console dotnet build dotnet run dotnet bin/Debug/net9.0/dotnet-9-test.dll */ var message = new Hello().GetHello(); Console.WriteLine( message ); public class Hello{ public string GetHello(){ return "Hello, world!"; } } }}} === dotnet-9-test.csproj === {{{#!highlight xml Exe net9.0 dotnet_9_test enable enable }}} == dotnetcore 9 - test api == === Setup docker DB with docker === {{{#!highlight sh docker network create mynet docker run -p 5432:5432 --rm --name postgres-server -e POSTGRES_PASSWORD=postgres --network mynet -d postgres:15.3-alpine docker exec -it postgres-server sh psql -U postgres \l \q exit # Create DB and schema docker exec -it postgres-server sh su postgres psql create user appuser with login password '12345678'; create database app; grant all privileges on database app to appuser; \q exit exit # Create schema, table and sequence docker exec -it postgres-server sh psql -U appuser -h localhost -W -d app create schema if not exists myschema; SET search_path TO myschema; GRANT ALL ON SCHEMA myschema TO appuser; create sequence if not exists device_seq; CREATE TABLE devices ( id integer PRIMARY KEY DEFAULT nextval('device_seq'), device varchar(128), apikey varchar(128) ); insert into devices(device,apikey) values('device','api'); select * from devices; \l \d \q exit }}} === Setup postgres DB in Debian === {{{#!highlight sh sudo apt install postgresql-15 ss -a -n | grep 5432 }}} === /etc/postgresql/15/main/pg_hba.conf === sudo nano /etc/postgresql/15/main/pg_hba.conf {{{#!highlight sh local all all peer host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256 host all all 0.0.0.0/0 password }}} === /etc/postgresql/15/main/postgresql.conf === sudo nano /etc/postgresql/15/main/postgresql.conf {{{#!highlight sh data_directory = '/var/lib/postgresql/15/main' hba_file = '/etc/postgresql/15/main/pg_hba.conf' ident_file = '/etc/postgresql/15/main/pg_ident.conf' external_pid_file = '/var/run/postgresql/15-main.pid' unix_socket_directories = '/var/run/postgresql' shared_buffers = 128MB dynamic_shared_memory_type = posix max_wal_size = 1GB min_wal_size = 80MB log_line_prefix = '%m [%p] %q%u@%d ' log_timezone = 'Europe/Lisbon' cluster_name = '15/main' datestyle = 'iso, mdy' timezone = 'Europe/Lisbon' default_text_search_config = 'pg_catalog.english' include_dir = 'conf.d' listen_addresses = '*' }}} === check connections === {{{#!highlight sh sudo service postgresql restart sudo service postgresql status pg_isready # /var/run/postgresql:5432 - accepting connections }}} === Create DB and schema === {{{#!highlight sh sudo bash su postgres psql create user appuser with login password '12345678'; create database app; grant all privileges on database app to appuser; create schema if not exists myschema; \q }}} === Create table and sequence === {{{ psql -U appuser -h 127.0.0.1 -W -d app psql -U appuser -h localhost -W -d app create schema if not exists myschema; SET search_path TO myschema; GRANT ALL ON SCHEMA myschema TO appuser; create sequence if not exists device_seq; CREATE TABLE devices ( id integer PRIMARY KEY DEFAULT nextval('device_seq'), device varchar(128), apikey varchar(128) ); insert into devices(device,apikey) values('device','api'); select * from devices; \q }}} === dotnet steps === {{{#!highlight sh cd ~/ mkdir -p test-api cd test-api dotnet new webapi dotnet add package Microsoft.AspNetCore.OpenApi dotnet add package Microsoft.EntityFrameworkCore.Design dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL dotnet add package Scalar.AspNetCore dotnet tool install --global dotnet-ef dotnet tool update --global dotnet-ef echo "export DOTNET_ROOT=$HOME/dotnetcore9/" >> ~/.bashrc echo "export DOTNET_ROOT=$HOME/dotnetcore9/" >> ~/.profile echo 'PATH="$HOME/.dotnet/tools:$PATH"' >> ~/.bashrc source ~/.bashrc dotnet-ef dotnet ef dotnet ef migrations add InitialCreate dotnet ef database update }}} === build.sh === {{{#!highlight sh #!/bin/sh dotnet build }}} === run.sh === {{{#!highlight sh #!/bin/sh dotnet bin/Debug/net9.0/test-api.dll }}} === appsettings.json === {{{#!highlight json { "AppName": "test-api app", "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "PostgresDB": "Host=localhost; Database=app; Username=appuser; Password=12345678; SearchPath=myschema;" }, "https_port": 8443, "Urls": "http://localhost:8081" } }}} === Program.cs === {{{#!highlight csharp using Microsoft.EntityFrameworkCore; using Scalar.AspNetCore; using Microsoft.Extensions.Configuration; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); builder.Services.AddDbContext(); builder.Services.AddScoped(); WebApplication app = builder.Build(); Console.WriteLine("appsettings.json Urls: {0}", app.Configuration["Urls"] ); Console.WriteLine("appsettings.json App name: {0}", app.Configuration["AppName"] ); Console.WriteLine("OpenAPI Scalar URL {0}/Scalar/v1", app.Configuration["Urls"] ); app.MapScalarApiReference(); app.MapOpenApi(); app.MapGet("/createtask/{description}", (string description, ITaskService service) => { return service.Create(description); }) .WithName("CreateTask"); app.MapGet("/gettasks", (ITaskService service) => { return service.GetAll(); }) .WithName("GetTasks"); app.Run(); public class DataContext : DbContext { protected readonly IConfiguration Configuration; public DataContext(IConfiguration configuration) { Configuration = configuration; } protected override void OnConfiguring(DbContextOptionsBuilder options) { // connect to postgres with connection string from app settings options.UseNpgsql(Configuration.GetConnectionString("PostgresDB")); } public DbSet Tasks { get; set; } } public class Task { public int Id { get; set; } public required string Description { get; set; } } public interface ITaskService { IEnumerable GetAll(); int Create(string description); } public class TaskService : ITaskService { private DataContext dbcontext; public TaskService(DataContext context) { dbcontext = context; } public int Create(string description) { var task = new Task() { Description = description }; dbcontext.Tasks.Add(task); dbcontext.SaveChanges(); return task.Id; } public IEnumerable GetAll() { return dbcontext.Tasks; } } }}}