Coder Social home page Coder Social logo

api-mediatr's Introduction

Api-MediatR

Projeto em asp.net core c# para uma arquitetura de API usando o conceito de CQRS com MediatR (Command, Handlers).

Este projeto utilize o Docker e Docker-Compose para criar o container de uma API C#.

Dependências

Abaixo as depedências do Nuget para os projetos (Core, Data, WebApi e UnitTests)

  <!--Core-->
  <ItemGroup>
    <PackageReference Include="MediatR" Version="9.0.0" />
    <PackageReference Include="FluentValidation" Version="9.5.1" />
  </ItemGroup>

  <!--Data-->
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.12" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.12" />
  </ItemGroup>

  <!--WebApi-->
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.12" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.12" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.12" />
    <PackageReference Include="MediatR" Version="9.0.0" />
    <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.0.7" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
  </ItemGroup>

  <!--UnitTest-->
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
    <PackageReference Include="xunit" Version="2.4.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="coverlet.collector" Version="1.3.0">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference> 
    <PackageReference Include="Moq" Version="4.16.1" />
    <PackageReference Include="Moq.AutoMock" Version="2.3.0" />
    <PackageReference Include="MediatR" Version="9.0.0" />
    <PackageReference Include="FluentAssertions" Version="5.10.3" />
  </ItemGroup>

Setup do pipeline da WebApi (Configure e ConfigureSerivces)

Vamos adicionar o Cors, as dependências, Swagger, Jwt e opções de serialização do JSON

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
        services.AddControllers();

        services.AddDependencies(Configuration);
        services.AddSwaggerDoc();
        services.AddJwt(Configuration);

        services.AddControllersWithViews()
                .AddNewtonsoftJson(options => {
                    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                    options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
                });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseGlobalExceptions();
        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseCors(x => x
           .AllowAnyOrigin()
           .AllowAnyMethod()
           .AllowAnyHeader());

        app.UseAuthentication();
        app.UseAuthorization();
        app.UseStaticFiles();

        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint(url: "/swagger/v1/swagger.json", name: "Sample Api");
        });

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

Pasta SETUP

Na pasta setup iremos configurar as seguintes extensões para o IServiceCollection, IApplicationBuilder.

Tratamento Global de Exceptions

  public static void UseGlobalExceptions(this IApplicationBuilder app)
  {
      app.UseExceptionHandler(builder =>
      {
          builder.Run(async ctx =>
          {
              var errorApp = ctx.Features.Get<IExceptionHandlerFeature>();
              var ex = errorApp.Error;

              ctx.Response.StatusCode = (int)ex.GetStatusCode();
              ctx.Response.ContentType = "application/json";

              var success = false;
              var message = ex.Message;
              var messageType = ex.GetMessageType();

              var strJson = $@"{{ ""sucess"": {success}, ""message"": ""{message}"", ""message_type"": ""{messageType}"" }}";
              await ctx.Response.WriteAsync(strJson);
          });
      }); 
  }

Autenticação/Autorização por JWT

    public static void AddJwt(this IServiceCollection services, IConfiguration configuration)
    {
        var key = Encoding.ASCII.GetBytes(configuration.GetSection("Jwt").GetValue<string>("SecretKey"));
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });
    }

Documentação da API usando Swagger

    public static IServiceCollection AddSwaggerDoc(this IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc(name: "v1", new OpenApiInfo { Title = "Sample Api", Version = "v1" });

            var definition = new OpenApiSecurityScheme
            {
                In = ParameterLocation.Header,
                Description = "Por favor, insira no campo a palavra 'Bearer', seguida por espaço e JWT",
                Name = "Authorization",
                Type = SecuritySchemeType.ApiKey
            };
            c.AddSecurityDefinition("Bearer", definition);
            c.AddSecurityRequirement(new OpenApiSecurityRequirement()
            {
                {
                  new OpenApiSecurityScheme
                  {
                    Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" },
                    Scheme = "oauth2",
                    Name = "Bearer",
                    In = ParameterLocation.Header
                  },
                  new List<string>()
                }
            });
        });

        return services;
    }

Configuração do Container de Injeção de Dependências

Usaremos o MediatR, Context do Entity e as nossas classes de (Repositories, Services, Handlers, Queries ...)

    public static IServiceCollection AddDependencies(this IServiceCollection services, IConfiguration configuration)
    {
        AddQueries(services);
        AddRepositories(services);
        AddHandlers(services);

        services.AddMediatR(typeof(Startup));

        services.AddDbContext<ApiSampleContext>(options =>
                    options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));

        return services;
    }

    private static void AddQueries(IServiceCollection services)
    {
        services.AddScoped<IClienteQuery, ClienteQuery>();
    }

    private static void AddRepositories(IServiceCollection services)
    { 
        services.AddScoped<IClienteRepository, ClienteRepository>();
        services.AddScoped<IVendaRepository, VendaRepository>();
    }

    private static void AddHandlers(IServiceCollection services)
    {
        services.AddScoped<IRequestHandler<CriarClienteCommand, bool>, ClienteCommandHandler>();
        services.AddScoped<IRequestHandler<AlterarClienteCommand, bool>, ClienteCommandHandler>();
        services.AddScoped<IRequestHandler<ExcluirClienteCommand, bool>, ClienteCommandHandler>();

        services.AddScoped<IRequestHandler<CriarVendaCommand, VendaCommandResult>, VendaCommandHandler>();
    }
}

api-mediatr's People

Contributors

diogoschimm avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.