Skip to content

Joaosilgo/dotnet-webapi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌮 DOTNET API


Info

dotnet add dotnet-webapi  package Microsoft.EntityFrameworkCore.InMemory --version 5.0.6
dotnet add package Microsoft.AspNetCore.Authentication
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Hangfire.Core --version 1.7.23
dotnet add package Hangfire.AspNetCore --version 1.7.23
dotnet add package Hangfire.MemoryStorage --version 1.7.0
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson --version 5.0.7
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --version 5.0.1
dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore --version 5.0.7


In-memory database provider for Entity Framework Core (to be used for testing purposes)

Postman

Postman

Github

Github

GitHub é uma plataforma de hospedagem de código-fonte e arquivos com controle de versão usando o Git. Ele permite que programadores, utilitários ou qualquer usuário cadastrado na plataforma contribuam em projetos privados e/ou Open Source de qualquer lugar do mundo.

DbInitializer

Swagger


TO-DO

To DO

  • In-memory database provider for Entity Framework Core (to be used for testing purposes)

  • Setting up Swagger (.NET Core) using the Authorization headers (Bearer)

  • Autenticação e Autorização via Token (Bearer e JWT)

  • Setup Docker Container and Deploy in Heroku

  • IncludeXmlComments in Swagger

  • Hangfire Core to perform background processing/tasks and Jobs

  • Override IDashboardAuthorizationFilter to CustomAuthorizationFilter to Return Hangfire DashBoard in Production (It was Protected By default)

  • [EnableCors] To Solve the Proble with Cors Policy

  • RespectBrowserAcceptHeader

  • Handle JSON Patch requests

  • Contact the media


Docker

Docker

Create a Dockerfile or generate in CRL+P Add Docker Compose

code Dockerfile
docker build .

So that we can Deploy in Heroku via Docker In Dockerfile change:

# ENTRYPOINT ["dotnet", "<app-name>.dll"]
# Opção utilizada pelo Heroku
CMD ASPNETCORE_URLS=http://*:$PORT dotnet <app-name>.dll

Deploy Heroku

docker build .
heroku login
heroku apps:create dotnet-webapi
heroku container:login
heroku container:push web -a dotnet-webapi
heroku container:release web -a dotnet-webapi
heroku logs --tail
Schemas
Category
Business
WeatherForecast
Syntax URL
Swagger Swagger
Paragraph Text
echo "# dotnet-webapi" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/Joaosilgo/dotnet-webapi.git
git push -u origin main

JSON Patch?

JSON Patch is a format for describing changes to a JSON document. It can be used to avoid sending a whole document when only a part has changed. When used in combination with the HTTP PATCH method, it allows partial updates for HTTP APIs in a standards compliant way.

The patch documents are themselves JSON documents.

Simple example

The original document

    {
      "baz": "qux",
      "foo": "bar"
    }

The patch

    [
      { "op": "replace", "path": "/baz", "value": "boo" },
      { "op": "add", "path": "/hello", "value": ["world"] },
      { "op": "remove", "path": "/foo" }
    ]

The result

    {
      "baz": "boo",
      "hello": ["world"]
    }

How it works

A JSON Patch document is just a JSON file containing an array of patch operations. The patch operations supported by JSON Patch are "add", "remove", "replace", "move", "copy" and "test". The operations are applied in order: if any of them fail then the whole patch operation should abort.

CACHE

"A distributed cache is a cache shared by multiple app servers, typically maintained as an external service to the app servers that access it. A distributed cache can improve the performance and scalability of an ASP.NET Core app, especially when the app is hosted by a cloud service or a server farm."... ..."Caching solutions usually rely on in-memory storage to provide fast retrieval of cached data, but memory is a limited resource and costly to expand. Only store commonly used data in a cache. Generally, a Redis cache provides higher throughput and lower latency than a SQL Server cache. However, benchmarking is usually required to determine the performance characteristics of caching strategies."

Setup Redis Db in Heroku via REDIS_URL

services.AddStackExchangeRedisCache(options =>
{
    var tokens = Configuration["REDIS_URL"].Split(':', '@');
    options.ConfigurationOptions = ConfigurationOptions.Parse(string.Format("{0}:{1},password={2}", tokens[3], tokens[4], tokens[2]));
});

Health Checks

Testing

Log Problems

1.0 Configuring Authorization

"Hangfire Dashboard exposes sensitive information about your background jobs, including method names and serialized arguments as well as gives you an opportunity to manage them by performing different actions – retry, delete, trigger, etc. So it is really important to restrict access to the Dashboard.

To make it secure by default, only local requests are allowed, however you can change this by passing your own implementations of the IDashboardAuthorizationFilter interface, whose Authorize method is used to allow or prohibit a request. The first step is to provide your own implementation."

To fix the Dashboard view in Production we have to Make

using Hangfire.Dashboard;

namespace dotnet_webapi.Services
{
    public class CustomAuthorizationFilter : IDashboardAuthorizationFilter
    {
        public bool Authorize(DashboardContext context)
        {
            return true;//we can make a condition to just retrive if a certain User/Role is Logged 
        }
    }
}

2.0 JSON Patch and Swagger

"Swashbuckle.AspNetCore doesn't work propertly with this type JsonPatchDocument, which doesn’t represent the expected patch request doument."

You need to custome a document filter to modify the generated specification.

using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace dotnet_webapi.Services
{
   public class JsonPatchDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        var schemas = swaggerDoc.Components.Schemas.ToList();
        foreach (var item in schemas)
        {
            if (item.Key.StartsWith("Operation") || item.Key.StartsWith("JsonPatchDocument"))
                swaggerDoc.Components.Schemas.Remove(item.Key);
        }

        swaggerDoc.Components.Schemas.Add("Operation", new OpenApiSchema
        {
            Type = "object",
            Properties = new Dictionary<string, OpenApiSchema>
            {
                {"op", new OpenApiSchema{ Type = "string" } },
                {"value", new OpenApiSchema{ Type = "string"} },
                {"path", new OpenApiSchema{ Type = "string" } }
            }
        });

        swaggerDoc.Components.Schemas.Add("JsonPatchDocument", new OpenApiSchema
        {
            Type = "array",
            Items = new OpenApiSchema
            {
                Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Operation" }
            },
            Description = "Array of operations to perform"
        });

        foreach (var path in swaggerDoc.Paths.SelectMany(p => p.Value.Operations)
        .Where(p => p.Key == Microsoft.OpenApi.Models.OperationType.Patch))
        {
            foreach (var item in path.Value.RequestBody.Content.Where(c => c.Key != "application/json-patch+json"))
                path.Value.RequestBody.Content.Remove(item.Key);
            var response = path.Value.RequestBody.Content.Single(c => c.Key == "application/json-patch+json");
            response.Value.Schema = new OpenApiSchema
            {
                Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "JsonPatchDocument" }
            };
        }
    }
}
}