QPANC - Parte 5 - ASP.NET - Documentação Interativa com Swagger
Tags: quasar, postgres, aspnetcore, docker
Published: 2020-04-19 23:36:23

> **QPANC** são as iniciais de **Q**uasar **P**ostgreSQL **A**SP **N**ET **C**ore.

  * [Source](https://github.com/TobyMosque/qpanc)
  * [Introdução](https://dev.to/quasar-pt-br/arquiteturando-uma-aplicacao-com-quasar-postgresql-asp-net-core-e-docker-introducao-o7o)
  * [Parte I - ASP.NET - Inicializando os Projetos](https://dev.to/quasar-pt-br/qpanc-parte-1-asp-net-inicializando-os-projetos-lkm)
  * [Parte 2 - PostgreSQL](https://dev.to/quasar-pt-br/qpanc-parte-2-postgresql-51pb)
  * [Parte 3 - ASP.NET - Registrando Serviços e Lendo Variáveis de Ambiente](https://dev.to/quasar-pt-br/qpanc-parte-3-asp-net-registrando-servicos-e-lendo-variaveis-de-ambiente-3do2)
  * [Parte 4 - ASP.NET - Entity Framework e ASP.NET Core Identity](https://dev.to/quasar-pt-br/qpanc-parte-4-asp-net-entity-framework-e-asp-net-core-identity-40f9)
  * [Parte 5 - ASP.NET - Documentação Interativa com Swagger](https://dev.to/quasar-pt-br/qpanc-parte-5-asp-net-documentacao-interativa-com-swagger-4n0o)
  * [Parte 6 - ASP.NET - Regionalização](https://dev.to/quasar-pt-br/qpanc-parte-6-asp-net-regionalizacao-13p5)
  * [Parte 7 - ASP.NET - Autenticação e Autorização](https://dev.to/quasar-pt-br/qpanc-parte-7-asp-net-autenticacao-e-autorizacao-bpd)
  * [Parte 8 - ASP.NET - CORS](https://dev.to/quasar-pt-br/qpanc-parte-8-asp-net-cors-52dn)
  * [Parte 9 - Quasar - Criação e Configuração do Projeto](https://dev.to/quasar-pt-br/qpanc-parte-9-quasar-criacao-e-configuracao-do-projeto-5hbi)
  * [Parte 10 - Quasar - Configurações e Customizações](https://dev.to/quasar-pt-br/qpanc-parte-10-quasar-configuracoes-e-customizacoes-2i86)
  * [Parte 11 - Quasar - Componentes - Diferença entre SPA e SSR](https://dev.to/quasar-pt-br/qpanc-parte-11-quasar-componentes-diferenca-entre-spa-e-ssr-1a3c)
  * [Parte 12 - Quasar - Serviços](https://dev.to/quasar-pt-br/qpanc-parte-12-quasar-servicos-4e61)
  * [Parte 13 - Quasar - Regionalização e Stores](https://dev.to/quasar-pt-br/qpanc-parte-13-quasar-regionalizacao-e-stores-1kep)
  * [Parte 14 - Quasar - Consumindo a API](https://dev.to/quasar-pt-br/qpanc-parte-14-quasar-consumindo-a-api-fn6)
  * [Parte 15 - Quasar - Login](https://dev.to/quasar-pt-br/qpanc-parte-15-quasar-login-jc6)
  * [Parte 16 - Quasar - Áreas Protegidas](https://dev.to/quasar-pt-br/qpanc-parte-16-quasar-areas-protegidas-3jkn)
  * [Parte 17 - Quasar - Registro](https://dev.to/quasar-pt-br/qpanc-parte-17-quasar-registro-3b8c)
  * [Parte 18 - Docker - Maquina Virtual Linux](https://dev.to/quasar-pt-br/qpanc-parte-18-docker-maquina-virtual-linux-g5c)
  * [Parte 19 - Docker - Registro e Build](https://dev.to/quasar-pt-br/qpanc-parte-19-docker-registro-e-build-31i4)
  * [Parte 20 - Docker - Traefik e Publicação](https://dev.to/quasar-pt-br/qpanc-parte-20-docker-traefik-e-publicacao-3g3d)
  * [Demo Online](https://qpanc.tobiasmesquita.dev)

##10 Documentação Interativa

Agora que terminamos de configurar o Banco de Dados e a camada da aplicação responsável por acessa-lo, iremos trabalhar sobre a API REST, e começaremos pelo Swagger, que ia nós prover uma documentação interativa para a nossa API.

Vá até o projeto `./QPANC.Api` e adicione o pacote:

```
cd QPANC.Api
dotnet add package Swashbuckle.AspNetCore
```

Agora, iremos criar um Middleware, para que apenas desenvolvedores possam acessar acessar a documentação interativa.

**./QPANC.Api/Middlewares/SwaggerBasicAuthMiddleware.cs**
```cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using QPANC.Domain.Identity;
using System;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace QPANC.Api.Middlewares
{
    public class SwaggerBasicAuthMiddleware
    {
        private readonly RequestDelegate _next;

        public SwaggerBasicAuthMiddleware(RequestDelegate next)
        {
            this._next = next;
        }

        public async Task InvokeAsync(HttpContext context, UserManager<User> userManager)
        {
            if (context.Request.Path.StartsWithSegments("/swagger"))
            {
                var isAuthorized = false;
                string authorization = context.Request.Headers["Authorization"];
                if (authorization != default && authorization.StartsWith("Basic "))
                {
                    var encoded = authorization.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();

                    var binary = Convert.FromBase64String(encoded);
                    var decoded = Encoding.UTF8.GetString(binary).Split(':', 2);
                    var username = decoded[0];
                    var password = decoded[1];
                    var user = await userManager.FindByNameAsync(username + "@qpanc.app");
                    if (user != default)
                    {
                        var isAuthenticated = await userManager.CheckPasswordAsync(user, password);
                        if (isAuthenticated)
                        {
                            isAuthorized = await userManager.IsInRoleAsync(user, "Developer");
                        }
                    }
                }
                if (isAuthorized)
                {
                    await this._next.Invoke(context);
                }
                else
                {
                    context.Response.Headers["WWW-Authenticate"] = "Basic";
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                }
            }
            else
            {
                await this._next.Invoke(context);
            }
        }
    }
}
```

então, configure o Swagger no `./QPANC.Api/Startup.cs`

```cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using QPANC.Api.Middlewares;

namespace QPANC.Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSwaggerGen(config =>
            {
                config.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey
                });

                var requirements = new OpenApiSecurityRequirement();
                var bearerSchema = new OpenApiSecurityScheme()
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    },
                    Scheme = "oauth2",
                    Name = "Bearer",
                    In = ParameterLocation.Header
                };
                requirements.Add(bearerSchema, new string[] { });
                config.AddSecurityRequirement(requirements);
                config.SwaggerDoc("v1", new OpenApiInfo
                {
                    Title = "API - QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker",
                    Description = "API - QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker",
                    Version = "v1",
                    Contact = new OpenApiContact
                    {
                        Name = "QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker",
                        Email = "developer@qpanc.app",
                        Url = new Uri("http://www.qpanc.app")
                    },
                });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISeeder seeder)
        {
            app.UseAuthentication();

            app.UseAuthorization();

            app.UseMiddleware<SwaggerBasicAuthMiddleware>();
            app.UseSwagger(c =>
            {
                c.RouteTemplate = "swagger/{documentName}/swagger.json";
            });
            app.UseSwaggerUI(c =>
            {

                c.SwaggerEndpoint("/swagger/v1/swagger.json", "QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker");
                c.RoutePrefix = "swagger";
            });
        }
    }
}
```

Execute a aplicação e acesse o path 'http://localhost:34512/swagger', se estiver utilizando o Visual Studio, poderá atualizar as propriedades do projeto `./QPANC` em `Properties` > `Debug` > `Web Server Settings` > `http://localhost:34512/swagger`

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/881ku7buabz8ibq501y0.png)

Você deve ter notado que foi necessário informar um usuário e uma senha para acessar a documentação, o que pode ser um incomodo durante o desenvolvimento, neste caso, podemos desativar o middleware durante o desenvolvimento.

```cs
namespace QPANC.Api
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISeeder seeder)
        {
            if (!env.IsDevelopment())
            {
                app.UseMiddleware<SwaggerBasicAuthMiddleware>();
            }
        }
    }
}
```