{"id":19029205,"url":"https://github.com/sulmar/vavatech-dotnet-core-pwpw","last_synced_at":"2026-06-15T01:38:11.921Z","repository":{"id":38048776,"uuid":"212330714","full_name":"sulmar/vavatech-dotnet-core-pwpw","owner":"sulmar","description":"Przykłady ze szkolenia .NET Core","archived":false,"fork":false,"pushed_at":"2022-12-08T06:14:52.000Z","size":44,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-21T20:13:22.823Z","etag":null,"topics":["csharp","net-core-2-2","signalr-client","signalr-core","webapi-core"],"latest_commit_sha":null,"homepage":"https://vavatech.pl","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sulmar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-02T12:08:38.000Z","updated_at":"2019-10-16T06:17:32.000Z","dependencies_parsed_at":"2023-01-24T16:15:30.797Z","dependency_job_id":null,"html_url":"https://github.com/sulmar/vavatech-dotnet-core-pwpw","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sulmar/vavatech-dotnet-core-pwpw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulmar%2Fvavatech-dotnet-core-pwpw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulmar%2Fvavatech-dotnet-core-pwpw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulmar%2Fvavatech-dotnet-core-pwpw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulmar%2Fvavatech-dotnet-core-pwpw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sulmar","download_url":"https://codeload.github.com/sulmar/vavatech-dotnet-core-pwpw/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulmar%2Fvavatech-dotnet-core-pwpw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34344440,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","net-core-2-2","signalr-client","signalr-core","webapi-core"],"created_at":"2024-11-08T21:13:35.794Z","updated_at":"2026-06-15T01:38:11.895Z","avatar_url":"https://github.com/sulmar.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# .NET Core\n\n## Przydatne komendy CLI\n- ``` dotnet --list-sdks ``` - wyświetlenie listy zainstalowanych SDK\n- ``` dotnet new globaljson ``` - utworzenie pliku global.json\n- ``` dotnet new globaljson --sdk-version {version} ``` - utworzenie pliku global.json i ustawienie wersji SDK\n- ``` dotnet new --list ``` - wyświetlenie listy dostępnych szablonów\n- ``` dotnet new {template} -o {output} ``` - utworzenie nowego projektu w podanym katalogu\n- ``` dotnet restore ``` - pobranie bibliotek nuget na podstawie pliku projektu\n- ``` dotnet build ``` - kompilacja projektu\n- ``` dotnet run ``` - uruchomienie projektu\n- ``` dotnet run {app.dll}``` - uruchomienie aplikacji\n- ``` dotnet test ``` - uruchomienie testów jednostkowych\n- ``` dotnet run watch``` - uruchomienie projektu w trybie śledzenia zmian\n- ``` dotnet test ``` - uruchomienie testów jednostkowych w trybie śledzenia zmian\n- ``` dotnet add {project.csproj} reference {library.csproj} ``` - dodanie odwołania do biblioteki\n- ``` dotnet remove {project.csproj} reference {library.csproj} ``` - usunięcie odwołania do biblioteki\n- ``` dotnet new sln ``` - utworzenie nowego rozwiązania\n- ``` dotnet sln {solution.sln} add {project.csproj}``` - dodanie projektu do rozwiązania\n- ``` dotnet sln {solution.sln} remove {project.csproj}``` - usunięcie projektu z rozwiązania\n- ``` dotnet publish -c Release -r {platform}``` - publikacja aplikacji\n- ``` dotnet publish -c Release -r win10-x64``` - publikacja aplikacji dla Windows\n- ``` dotnet publish -c Release -r linux-x64``` - publikacja aplikacji dla Linux\n- ``` dotnet publish -c Release -r osx-x64``` - publikacja aplikacji dla MacOS\n- ``` dotnet add package {package-name} ``` - dodanie pakietu nuget do projektu\n- ``` dotnet remove package {package-name} ``` - usunięcie pakietu nuget do projektu\n\n## Konfiguracja\n\n- Utworzenie klasy opcji\n~~~ csharp\npublic class CustomerOptions\n{\n    public int Quantity { get; set; }\n}\n~~~\n\n\n- Plik konfiguracyjny appsettings.json\n\n~~~ json\n{\n  \"CustomersModule\": {\n    \"Quantity\": 40\n  },\n  \n  ~~~\n\n- Instalacja biblioteki\n\n~~~ bash\n dotnet add package Microsoft.Extensions.Options\n~~~\n\n- Użycie opcji\n\n~~~ csharp\n\npublic class FakeCustomersService\n{\n   private readonly CustomerOptions options;\n\n    public FakeCustomersService(IOptions\u003cCustomerOptions\u003e options)\n    {\n        this.options = options.Value;\n    }\n}\n       \n~~~\n\n- Konfiguracja opcji\n\n~~~ csharp\npublic class Startup\n    {\n        public IConfiguration Configuration { get; }\n    \n        public Startup(IHostingEnvironment env)\n        {\n            var builder = new ConfigurationBuilder()\n                .SetBasePath(env.ContentRootPath)\n                .AddJsonFile(\"appsettings.json\", optional: false)\n                .AddXmlFile(\"appsettings.xml\", optional: true)\n                .AddJsonFile($\"appsettings.{env.EnvironmentName}.json\", optional: true);\n\n            Configuration = builder.Build();\n\n        }\n        \n      public void ConfigureServices(IServiceCollection services)\n      {\n          services.Configure\u003cCustomerOptions\u003e(Configuration.GetSection(\"CustomersModule\"));\n      }\n    }\n~~~\n\n- Konfiguracja bez interfejsu IOptions\u003cT\u003e\n  \n~~~ csharp\n  public void ConfigureServices(IServiceCollection services)\n        {\n            var customerOptions = new CustomerOptions();\n            Configuration.GetSection(\"CustomersModule\").Bind(customerOptions);\n            services.AddSingleton(customerOptions);\n\n            services.Configure\u003cCustomerOptions\u003e(Configuration.GetSection(\"CustomersModule\"));\n        }\n\n~~~\n\n\n\n## REST API\n\n\n| Akcja  | Opis                  |\n|--------|-----------------------|\n| GET    | Pobierz               |\n| POST   | Utwórz                |\n| PUT    | Podmień               |\n| DELETE | Usuń                  |\n| PATCH  | Zmień częściowo       |\n| HEAD   | Czy zasób istnieje    |\n\n## Opcje serializacji json\n\nPlik Startup.cs\n\n~~~ csharp\n\npublic void ConfigureServices(IServiceCollection services)\n{\n  services.AddMvc()\n    .AddJsonOptions(options =\u003e\n    {\n        options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; // Wyłączenie generowania wartości null w jsonie\n        options.SerializerSettings.Converters.Add(new StringEnumConverter(camelCaseText: true));  // Serializacja enum jako tekst\n        options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; // Zapobieganie cyklicznej serializacji\n\n    })\n}\n~~~\n\n### Włączenie obsługi XML\n\n- Instalacja\n~~~ bash\ndotnet add package AddXmlSerializerFormatters\n~~~\n\n\nPlik Startup.cs\n\n~~~ csharp\n public void ConfigureServices(IServiceCollection services)\n {\n     services\n         .AddMvc(options =\u003e options.RespectBrowserAcceptHeader = true)\n         .AddXmlSerializerFormatters();\n }\n~~~\n\n### Przekazywanie formatu poprzez adres URL\n\n\n\n~~~ csharp\n\n// GET api/customers/10\n// GET api/customers/10.json\n// GET api/customers/10.xml\n\n[Route(\"api/[controller]\")]\npublic class CustomersController : ControllerBase\n{\n    [FormatFilter]\n    [HttpGet(\"{id:int}.{format?}\")]\n    public IActionResult GetById(int id)\n    {\n        if (!customerRepository.IsExists(id))\n            return NotFound();\n\n        var customer = customerRepository.Get(id);\n\n        return Ok(customer);\n    }\n}\n~~~\n\n\n## Autentyfikacja\n\n\n### Basic\nHeaders \n\n| Key   | Value  |\n|---|---|\n| Authorization | Basic {Base64(login:password)}  |\n\n\n### Utworzenie uchwytu\n\n~~~ csharp\n\n public class BasicAuthenticationHandler : AuthenticationHandler\u003cAuthenticationSchemeOptions\u003e\n    {\n        private readonly IUsersService usersService;\n\n        public BasicAuthenticationHandler(\n            IUsersService usersService,\n            IOptionsMonitor\u003cAuthenticationSchemeOptions\u003e options, \n            ILoggerFactory logger, \n            UrlEncoder encoder, \n            ISystemClock clock) : base(options, logger, encoder, clock)\n        {\n\n            this.usersService = usersService;\n        }\n\n        protected override async Task\u003cAuthenticateResult\u003e HandleAuthenticateAsync()\n        {\n\n            if (!Request.Headers.ContainsKey(\"Authorization\"))\n            {\n                return AuthenticateResult.Fail(\"Missing authorization header\");\n            }\n\n            var authHeader = AuthenticationHeaderValue.Parse(Request.Headers[\"Authorization\"]);\n            var credentialBytes = Convert.FromBase64String(authHeader.Parameter);\n            var credentials = Encoding.UTF8.GetString(credentialBytes).Split(\":\");\n\n            var username = credentials[0];\n            var password = credentials[1];\n\n            User user = usersService.Authenticate(username, password);\n\n            if (user == null)\n            {\n                return AuthenticateResult.Fail(\"Invalid username or password\");\n            }\n\n            IIdentity identity = new ClaimsIdentity(Scheme.Name);\n            ClaimsPrincipal principal = new ClaimsPrincipal(identity);\n\n            // IIdentity identity = new GenericIdentity(user.Login);\n\n            var ticket = new AuthenticationTicket(principal, Scheme.Name);\n\n            return AuthenticateResult.Success(ticket);\n\n        }\n    }\n~~~\n\n#### Rejestracja\nStartup.cs\n\n~~~ csharp\n public void ConfigureServices(IServiceCollection services)\n{\n\n    services.AddAuthentication(\"BasicAuthorization\")\n        .AddScheme\u003cAuthenticationSchemeOptions, BasicAuthenticationHandler\u003e(\"BasicAuthorization\", null);\n  }\n  \n public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n  {\n\n\n      app.UseAuthentication();\n      app.UseMvc();\n    }\n\n~~~\n\n### Token\nHeaders \n\n| Key   | Value  |\n|---|---|\n| Authorization | Bearer {token}  |\n\n\n### JWT\n\nhttps://github.com/sulmar/dotnet-core-jwt\n\n\n## OWIN\n\nStartup.cs\n\n~~~ csharp\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    app.UseOwin(pipeline =\u003e pipeline(next =\u003e OwinHandler));\n}\n            \npublic Task OwinHandler(IDictionary\u003cstring, object\u003e environment)\n{\n     string responseText = \"Hello World via OWIN\";\n     byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);\n\n    // OWIN Environment Keys: http://owin.org/spec/spec/owin-1.0.0.html\n\n    var requestMethod = (string) environment[\"owin.RequestMethod\"];\n    var requestScheme = (string) environment[\"owin.RequestScheme\"];\n    var requestHeaders = (IDictionary\u003cstring, string[]\u003e)environment[\"owin.RequestHeaders\"];\n    var requestQueryString = (string) environment[\"owin.RequestQueryString\"];         \n\n    var responseStream = (Stream)environment[\"owin.ResponseBody\"];\n\n    var responseHeaders = (IDictionary\u003cstring, string[]\u003e)environment[\"owin.ResponseHeaders\"];\n\n    responseHeaders[\"Content-Length\"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };\n    responseHeaders[\"Content-Type\"] = new string[] { \"text/plain\" };\n\n    return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);\n}\n\n~~~\n\n\n\n## Middleware\n\n\n### Run\n~~~ csharp\n public void Configuration(IAppBuilder app)\n{\n  app.Run(async context =\u003e await context.Response.WriteAsync(\"Hello World\"));\n}\n~~~\n\n\n### Uworzenie metody własnej warstwy pośredniej\n\n~~~ csharp\napp.Use(async (context, next) =\u003e\n{\n    Trace.WriteLine(String.Format(\"request: {0} - {1}\", context.Request.Method, context.Request.Path));\n\n    await next.Invoke();\n\n    Trace.WriteLine(String.Format(\"response: {0}\", context.Response.StatusCode));\n\n});\n~~~\n\n\n\n\n### Uworzenie klasy własnej warstwy pośredniej\n\nNa przykładzie przekazywania formatu poprzez URL, np. http://localhost:5000/api/values?format=application/xml\n\nRequestAcceptMiddleware.cs\n\n~~~ csharp\n public class RequestAcceptMiddleware\n    {\n        private readonly RequestDelegate next;\n\n        public RequestAcceptMiddleware(RequestDelegate next)\n        {\n            this.next = next;\n        }\n\n        public async Task InvokeAsync(HttpContext context)\n        {\n            var formatQuery = context.Request.Query[\"format\"];\n\n            if (!string.IsNullOrWhiteSpace(formatQuery))\n            {\n                context.Request.Headers.Remove(\"Accept\");\n                context.Request.Headers.Append(\"Accept\", new string[] { formatQuery });\n            }\n\n            // Call the next delegate/middleware in the pipeline\n            await next(context);\n\n        }\n    }\n    \n  \n  ~~~\n  \n   Startup.cs\n \n  \n~~~ csharp \npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n     app.UseMiddleware\u003cRequestAcceptMiddleware\u003e();\n}\n~~~\n  \n### Zastosowanie metody rozszerzającej\n  \nRequestAcceptMiddlewareExtensions.cs\n  \n~~~ csharp \n  public static class RequestAcceptMiddlewareExtensions\n  {\n      public static IApplicationBuilder UseRequestAccept(\n          this IApplicationBuilder builder)\n      {\n          return builder.UseMiddleware\u003cRequestAcceptMiddleware\u003e();\n      }\n  }\n~~~\n  \nStartup.cs\n\n~~~ csharp \npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    app.UseRequestAccept();\n}\n~~~\n\n### Mapowanie tras\n\n~~~ csharp \npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n\n    app.Map(\"/dashboard\", HandleMapTest1);\n\n    app.Map(\"/sensors\", node =\u003e\n      {\n          node.Map(\"/temp\", TempDelegate);\n          node.Map(\"/humidity\", HumidityDelegate);\n          node.Map(string.Empty, SensorsDelegate);\n      });\n}\n\nprivate void HumidityDelegate(IAppBuilder app)\n{\n    app.Run(async context =\u003e await context.Response.WriteAsync(\"1024 hPa\"));\n}\n\nprivate void TempDelegate(IAppBuilder app)\n{\n    app.Run(async context =\u003e await context.Response.WriteAsync(\"Temp 23C\"));\n}\n~~~\n\n### Mapowanie warunkowe\n~~~ csharp\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{       \n    app.MapWhen(context =\u003e context.Request.Headers.Get(\"Host\").StartsWith(\"localhost\"), LocalHostDelegate);\n }\n \nprivate void LocalHostDelegate(IAppBuilder app)\n{\n    app.Run(async context =\u003e await context.Response.WriteAsync(\"localhost\"));\n}\n\n~~~\n\n### Mapowanie akcji\n\n~~~ csharp\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {       \n\n            var rb = new RouteBuilder(app);\n\n            rb.Routes.Add(new Route(new MyRouter(), \"fib/{number:int}\",\n                app.ApplicationServices.GetService\u003cIInlineConstraintResolver\u003e()));\n\n            rb.MapGet(\"\", request =\u003e request.Response.WriteAsync(\"Hello World\"));\n\n            rb.MapGet(\"sensors\", request =\u003e request.Response.WriteAsync(\"Sensors\"));\n\n            rb.MapGet(\"sensors/{id:int}\", request =\u003e request.Response.WriteAsync($\"Sensor id {request.GetRouteValue(\"id\")}\"));\n\n            rb.MapPost(\"post\", request =\u003e request.Response.WriteAsync(\"Created\"));\n\n            app.UseRouter(rb.Build());\n~~~\n\n## Signal-R\n\n### Utworzenie koncetratora (huba)\n\nCustomersHub.cs\n\n~~~ csharp\n\npublic class CustomersHub : Hub\n{\n     public override Task OnConnectedAsync()\n     {\n         return base.OnConnectedAsync();\n     }\n\n     public Task CustomerAdded(Customer customer)\n     {\n         return this.Clients.Others.SendAsync(\"Added\", customer);\n     } \n     \n      public Task Ping(string message=\"Pong\")\n      {\n           return this.Clients.Caller.SendAsync(message);\n      }\n     \n}\n~~~\n\n### Rejestracja koncentratora\n\n~~~ csharp\n\npublic class Startup\n{\n    \n    public void ConfigureServices(IServiceCollection services)\n    {\n        services.AddSignalR();\n    }\n\n    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n    public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n    {\n        app.UseSignalR(routes =\u003e routes.MapHub\u003cCustomersHub\u003e(\"/hubs/customers\"));\n\n        if (env.IsDevelopment())\n        {\n            app.UseDeveloperExceptionPage();\n        }\n\n        app.Run(async (context) =\u003e\n        {\n            await context.Response.WriteAsync(\"Hello World!\");\n        });\n    }\n~~~\n\n### Utworzenie nadawcy\n\n\n~~~ csharp\n\nstatic async Task Main(string[] args)\n{\n    const string url = \"http://localhost:5000/hubs/customers\";\n\n    HubConnection connection = new HubConnectionBuilder()\n        .WithUrl(url)\n        .Build();\n\n    connection.Closed += ex =\u003e Task.Run(() =\u003e System.Console.WriteLine($\"ERROR {ex.Message}\"));\n    await connection.StartAsync();\n\n    Customer customer = new Customer\n    {\n        FirstName = \"Marcin\",\n        LastName = \"Sulecki\"\n    };\n\n    while (true)\n    {\n        await connection.SendAsync(\"CustomerAdded\", customer);\n        await Task.Delay(TimeSpan.FromSeconds(1));\n    }\n~~~\n\n\n### Utworzenie odbiorcy\n\n~~~ csharp\n\nstatic async Task Main(string[] args)\n{\n    const string url = \"http://localhost:5000/hubs/customers\";\n\n    // dotnet add package Microsoft.AspNetCore.SignalR.Client\n\n    HubConnection connection = new HubConnectionBuilder()\n        .WithUrl(url)\n        .Build();\n\n    connection.Closed +=  ex =\u003e Task.Run(()=\u003eSystem.Console.WriteLine($\"ERROR {ex.Message}\")); \n\n    await connection.StartAsync();            \n\n    connection.On\u003cCustomer\u003e(\"Added\", \n        customer =\u003e Console.WriteLine($\"Added customer {customer.FirstName}\"));\n}\n~~~\n\n### Wstrzykiwanie huba\n\nCustomersController.cs\n\n~~~ csharp\n\n public class CustomersController : ControllerBase\n {\n    private readonly IHubContext\u003cCustomersHub\u003e hubContext;\n   \n    public CustomersController(IHubContext\u003cCustomersHub\u003e hubContext)\n     {\n         this.hubContext = hubContext;\n     }\n     \n    [HttpPost]\n     public async Task\u003cIActionResult\u003e Post( Customer customer)\n     {\n         customersService.Add(customer);\n\n         await hubContext.Clients.All.SendAsync(\"Added\", customer);\n\n         return CreatedAtRoute(new { Id = customer.Id }, customer);\n     }\n }\n\n~~~\n\n### Autentykacja\n\nProgram.cs\n\n~~~ csharp\nstatic async Task Main(string[] args)\n{\n    const string url = \"http://localhost:5000/hubs/customers\";\n\n    var username = \"your-username\";\n    var password = \"your-password\";\n\n    var credentialBytes = Encoding.UTF8.GetBytes($\"{username}:{password}\");\n    var credentials = Convert.ToBase64String(credentialBytes);\n\n    string parameter = $\"Basic {credentials}\";\n\n    HubConnection connection = new HubConnectionBuilder()\n        .WithUrl(url, options =\u003e options.Headers.Add(\"Authorization\", parameter))\n        .Build();\n\n    await connection.StartAsync();        \n    await connection.SendAsync(\"CustomerAdded\", customer);\n}\n\n~~~\n\n### Utworzenie silnie typowanego huba\n\nCustomersHub.cs\n\n~~~ csharp\n\npublic interface ICustomersHub\n{\n    Task Added(Customer customer);\n}\n\npublic class CustomersHub : Hub\u003cICustomersHub\u003e\n{\n     public Task CustomerAdded(Customer customer)\n     {\n         return this.Clients.Others.Added(customer);\n     } \n}\n~~~\n\n### Wstrzykiwanie silnie typowanego huba\n\nCustomersController.cs\n\n~~~ csharp\n\n public class CustomersController : ControllerBase\n {\n    private readonly IHubContext\u003cCustomersHub, ICustomersHub\u003e hubContext;\n   \n    public CustomersController(IHubContext\u003cCustomersHub, ICustomersHub\u003e hubContext)\n     {\n         this.hubContext = hubContext;\n     }\n     \n    [HttpPost]\n     public async Task\u003cIActionResult\u003e Post( Customer customer)\n     {\n         customersService.Add(customer);\n\n         await hubContext.Clients.All.Added(customer);\n\n         return CreatedAtRoute(new { Id = customer.Id }, customer);\n     }\n }\n\n~~~\n\n\n### Grupy\n\n\n~~~ csharp\n\npublic async Task AddToGroup(string groupName)\n{\n    await Groups.AddToGroupAsync(Context.ConnectionId, groupName);\n\n    await Clients.Group(groupName).SendAsync(\"Send\", $\"{Context.ConnectionId} has joined the group {groupName}.\");\n}\n\npublic async Task RemoveFromGroup(string groupName)\n{\n    await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);\n\n    await Clients.Group(groupName).SendAsync(\"Send\", $\"{Context.ConnectionId} has left the group {groupName}.\");\n}\n\n~~~\n\n\n\n## Testy jednostkowe\n\n\n### NUnit\n\n\nUtworzenie projektu\n\n~~~ bash\ndotnet new nunit\n~~~\n\nPrzykładowa klasa\n\n~~~ csharp\npublic class Calculator\n{\n    public int Add(int x, int y) =\u003e x + y;\n}\n~~~\n\n\n#### Test\n~~~ csharp\n\n[TestClass]\npublic class UnitTest1\n{\n    [TestMethod]\n    public void TestMethod1()\n    {\n         var calculator = new Calculator();\n\n        var result = calculator.Add(2, 2);\n\n        Assert.AreEqual(4, result);\n    }\n}\n~~~\n\n\n### xUnit\n\nUtworzenie projektu\n\n~~~ bash\ndotnet new xunit\n~~~\n\nPrzykładowa klasa\n\n~~~ csharp\npublic class Calculator\n{\n    public int Add(int x, int y) =\u003e x + y;\n}\n~~~\n\n#### Fakt\n\n~~~ csharp\n[Fact]\n    public void Test1()\n    {\n        var calculator = new Calculator();\n\n        int result = calculator.Add(2, 2);\n\n        Assert.Equal(4, result);\n\n    }\n~~~\n\n#### Teoria - inlinedata\n\n~~~ csharp\n[Theory]\n[InlineData(1, 2, 3)]\n[InlineData(-4, -6, -10)]\n[InlineData(-2, 2, 0)]\n[InlineData(int.MinValue, -1, int.MaxValue)]\npublic void CanAddTheory(int value1, int value2, int expected)\n{\n    var calculator = new Calculator();\n    var result = calculator.Add(value1, value2);\n    Assert.Equal(expected, result);\n}\n~~~\n\n\n#### Teoria - classdata\n\n~~~ csharp\npublic class CalculatorTestData : TheoryData\u003cint, int, int\u003e\n{\n    public CalculatorTestData()\n    {\n        Add(1, 2, 3);\n        Add(-4, -6, -10);\n        Add(-2, 2, 0);\n        Add(int.MinValue, -1, int.MaxValue);\n        \n    }\n}\n\n[Theory]\n[ClassData(typeof(CalculatorTestData))]\npublic void CanAdd(int value1, int value2, int expected)\n{\n    var calculator = new Calculator();\n    var result = calculator.Add(value1, value2);\n    Assert.Equal(expected, result);\n}\n~~~\n\n\n#### Teoria - memberdata\n\n\n~~~ csharp\n\npublic static IEnumerable\u003cobject[]\u003e Data =\u003e\n        new List\u003cobject[]\u003e\n        {\n            new object[] { 1, 2, 3 },\n            new object[] { -4, -6, -10 },\n            new object[] { -2, 2, 0 },\n            new object[] { int.MinValue, -1, int.MaxValue },\n        };\n\n[Theory]\n  [MemberData(nameof(Data))]\n  public void CanAddTheoryMemberDataProperty(int value1, int value2, int expected)\n  {\n      var calculator = new Calculator();\n\n      var result = calculator.Add(value1, value2);\n\n      Assert.Equal(expected, result);\n  }\n~~~\n\n### FluentAssertions\n\n\n## Kontrola kondycji\n\n### Rejestrowanie kondycji\n\n#### Kondycja SQL Server\n\n~~~ bash\ndotnet add package AspNetCore.HealthChecks.SqlServer \n~~~\n\nStartup.cs\n\n~~~ csharp\n\npublic void ConfigureServices(IServiceCollection services)\n{\n services.AddHealthChecksUI()\n    .AddSqlServer(Configuration.GetConnectionStrings(\"MyConnection\");\n}\n\n~~~\n\n\n#### Kondycja DbContext\n\n~~~ bash\ndotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore\n~~~\n\nStartup.cs\n\n~~~ csharp\n\npublic void ConfigureServices(IServiceCollection services)\n{\n  services.AddDbContext\u003cAppDbContext\u003e(options =\u003e options.UseSqlServer(Configuration.GetConnectionString(\"MyConnection\"));\n            \n    services.AddHealthChecks()\n            .AddDbContextCheck\u003cAppDbContext\u003e();\n\n}\n\n~~~\n\n\n### Utworzenie własnej kontroli kondycji\n\n\nRandomHealthCheck.cs\n\n~~~ csharp\n\npublic class RandomHealthCheck  : IHealthCheck\n    {\n        public Task\u003cHealthCheckResult\u003e CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)\n        {\n            if (DateTime.UtcNow.Minute % 2 == 0)\n            {\n                return Task.FromResult(HealthCheckResult.Healthy());\n            }\n\n            return Task.FromResult(HealthCheckResult.Unhealthy(description: \"failed\"));\n        }\n    }\n~~~\n\nStartup.cs\n\n~~~ csharp\n\npublic void ConfigureServices(IServiceCollection services)\n{\n services.AddHealthChecks()\n             .AddCheck\u003cRandomHealthCheck\u003e(\"random\");\n}\n\n~~~\n\n### Dashboard\n\nInstalacja\n\n~~~ bash\ndotnet add package AspNetCore.HealthChecks.UI\n~~~\n          \n\nStartup.cs\n\n~~~ csharp\n\npublic void ConfigureServices(IServiceCollection services)\n{\n   services.AddHealthChecksUI();\n}\n\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    app.UseHealthChecks(\"/health\",  new HealthCheckOptions()\n      {\n          Predicate = _ =\u003e true,\n          ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse\n      });\n}\n~~~\n\nappsettings.json\n\n~~~ json\n\n \"HealthChecks-UI\": {\n    \"HealthChecks\": [\n      {\n        \"Name\": \"Http and UI on single project\",\n        \"Uri\": \"http://localhost:5000/health\"\n      }\n    ],\n    \"Webhooks\": [],\n    \"EvaluationTimeOnSeconds\": 10,\n    \"MinimumSecondsBetweenFailureNotifications\": 60\n  }\n  \n~~~\n\nWskazówka: Przejdź na http://localhost:5000/healthchecks-ui aby zobaczyc panel\n\n## Generowanie dokumentacji\nW formacie Swagger/OpenApi\n\n### Instalacja\n\n~~~ bash\ndotnet add TodoApi.csproj package Swashbuckle.AspNetCore\n~~~\n\n### Konfiguracja\n\nPlik Startup.cs\n\n~~~ csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n services\n      .AddSwaggerGen(c =\u003e c.SwaggerDoc(\"v1\", new Info { Title = \"My Api\", Version = \"1.0\" }));         \n} \n~~~\n\n~~~ csharp\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n   app.UseSwagger();\n\n            app.UseSwaggerUI(c =\u003e c.SwaggerEndpoint(\"/swagger/v1/swagger.json\", \"My API V1\"));\n }           \n~~~\n\n## Docker\n\n\n- Uruchomienie pierwszego kontenera\n~~~ bash\ndocker run ubuntu /bin/echo 'Hello world'\n~~~\n\n- Uruchomienie w trybie interaktywnym\n~~~ bash\ndocker run -i -t --rm ubuntu /bin/bash\n~~~\n\n### Przydatne komendy\n- ``` docker images ``` - lista wszystkich obrazów na twojej maszynie\n- ``` docker pull \u003cimage\u003e ``` - pobranie obrazu\n- ``` docker run \u003cimage\u003e ``` - uruchomienie obrazu (pobiera jeśli nie ma)\n- ``` docker ps ``` - lista wszystkich uruchomionych kontenerów na twojej maszynie\n- ``` docker ps -a``` - lista wszystkich przyłączonych ale nie uruchomionych kontenerów\n- ``` docker start \u003ccontainter_name\u003e ``` - uruchomienie kontenera wg nazwy\n- ``` docker stop \u003ccontainter_name\u003e ``` - zatrzymanie kontenera wg nazwy\n\n### Konteneryzacja aplikacji .NET Core\n\n* Utwórz plik Dockerfile\n\n~~~\nFROM microsoft/dotnet:2.0-sdk\nWORKDIR /app\n\n# copy csproj and restore as distinct layers\nCOPY *.csproj ./\nRUN dotnet restore\n\n# copy and build everything else\nCOPY . ./\nRUN dotnet publish -c Release -o out\nENTRYPOINT [\"dotnet\", \"out/Hello.dll\"]\n~~~\n\n\n## ngrok\n\n- Uruchomienie\n\n``` bash\nngrok http 5000\n```\n\n- Interfejs webowy\n\n```\nhttp://127.0.0.1:4040\n```\n\n- API\n\n```\nhttp://127.0.0.1:4040/api\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsulmar%2Fvavatech-dotnet-core-pwpw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsulmar%2Fvavatech-dotnet-core-pwpw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsulmar%2Fvavatech-dotnet-core-pwpw/lists"}