ASPNET 6 Web Api Basic Tutorial 2 / 2 (Swagger, SeriLog, MediatR, EntityFrameworkCore, Scrutor)

2022. 1. 1. 23:54ASPNET/WebApi

반응형
  1. Create Project
  2. Create Controller
  3. Add Swagger
  4. Add SeriLog
  5. Add MediatR
  6. Add EntityFramework Core
  7. Add Migration
  8. Apply Database
  9. 기타 초기화
  10. Add Web Api 
  11. Refactoring with Extension Method

9. 기타 초기화

Scrutor 추가
 
개발자 프롬프트에서 프로젝트 폴더로 이동 
(현재 .sln 파일이 있는 폴더라면 .csproj 파일이 있는 폴더로 이동)
 
아래 명령 실행
 
dotnet add package Scrutor
 
Injectables 폴더 추가
 
Injectable.cs 추가
namespace WebApiBasicTutorial.Injectables
{
    public interface IInjectableService { }
    public interface ITransientService : IInjectableService { }
    public interface IScopedService : IInjectableService { }
    public interface ISingletonService : IInjectableService { }
}
 
 
Program.cs 에 다음 코드 추가
 
using WebApiBasicTutorial.Injectables;
...
...
builder.Services.Scan(scan => scan
                            .FromAssemblies(AssemblyHelper.GetAllAssemblies())
                            .AddClasses(classes => classes.AssignableTo<ITransientService>())
                            .AsImplementedInterfaces()
                            .WithTransientLifetime()
                            .AddClasses(classes => classes.AssignableTo<IScopedService>())
                            .AsImplementedInterfaces()
                            .WithScopedLifetime()
                            .AddClasses(classes => classes.AssignableTo<ISingletonService>())
                            .AsImplementedInterfaces()
                            .WithSingletonLifetime()
                            );
 
 
 
Logger Customize
 
Logger folder 추가 
 
IApiLogger.cs 추가
using System.Runtime.CompilerServices;

namespace WebApiBasicTutorial.Logger
{
    public interface IApiLogger : ITransientService
    {
        void Log(LogLevel logLevel, string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args);

        void LogTrace(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args);
        void LogDebug(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args);
        void LogInformation(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args);
        void LogWarning(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args);
        void LogError(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args);
        void LogError(Exception exception, string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args);
    }
}
 
ApiLogger.cs 추가
using System.Runtime.CompilerServices;

namespace WebApiBasicEmpty.CustomLogger
{
    public class ApiLogger : IApiLogger
    {

        private ILogger _logger;
        public ApiLogger(ILogger<ApiLogger> logger) => _logger = logger;
        
        public void Log(LogLevel logLevel, string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args)
        {
            _logger.Log(logLevel, message, membername, filePath, lineNumber, args);
        }

        public void LogDebug(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args)
        {
            _logger.LogDebug(CreateLogMessage(message, membername, filePath, lineNumber), args);
        }

        public void LogError(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args)
        {
            _logger.LogError(CreateLogMessage(message, membername, filePath, lineNumber), args);
        }

        public void LogError(Exception exception, string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args)
        {
            _logger.LogError(exception, CreateLogMessage(message, membername, filePath, lineNumber), args);
        }

        public void LogInformation(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args)
        {
            _logger.LogInformation(CreateLogMessage(message, membername, filePath, lineNumber), args);
        }

        public void LogTrace(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args)
        {
            _logger.LogTrace(CreateLogMessage(message, membername, filePath, lineNumber), args);
        }

        public void LogWarning(string message, [CallerMemberName] string membername = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, params object[] args)
        {
            _logger.LogWarning(CreateLogMessage(message, membername, filePath, lineNumber), args);
        }

        private string CreateLogMessage(string message, string memberName, string filePath, int lineNumber)
        {
            return $"[{memberName}] {message}. \nfilePath = {filePath} : line = {lineNumber}";
        }

    }
}
 
 

Tracer 추가

Api Tracer with Middleware (Serilog)
 
Middleware folder 추가 
ApiLoggingMiddleware.cs 추가
using System.Text;
using WebApiBasicTutorial.Logger;

namespace WebApiBasicTutorial.Middleware
{
    public class ApiLoggingMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IApiLogger _logger;

        public ApiLoggingMiddleware(RequestDelegate next, IApiLogger logger)
        {
            _next = next;
            _logger = logger;
        }
        public async Task Invoke(HttpContext context)
        {
            var request = await FormatRequest(context.Request);
            var path = context.Request?.Path.ToString() ?? string.Empty;

            _logger.LogInformation(request);

            var originalBodyStream = context.Response.Body;

            using (var responseBody = new MemoryStream())
            {
                context.Response.Body = responseBody;
                await _next(context);
                var response = await FormatResponse(context.Response);
                _logger.LogInformation(response);
                await responseBody.CopyToAsync(originalBodyStream);
            }


        }

        private async Task<string> FormatResponse(HttpResponse response)
        {
            response.Body.Seek(0, SeekOrigin.Begin);

            string text = await new StreamReader(response.Body).ReadToEndAsync();

            response.Body.Seek(0, SeekOrigin.Begin);

            return $"{response.StatusCode}: {text}";

        }

        private async Task<string> FormatRequest(HttpRequest request)
        {
            request.EnableBuffering();
            var body = request.Body;
            var buffer = new byte[Convert.ToInt32(request.ContentLength)];
            await request.Body.ReadAsync(buffer, 0, buffer.Length);

            var bodyAsText = Encoding.UTF8.GetString(buffer);
            body.Seek(0, SeekOrigin.Begin);
            request.Body = body;

            return $"{request.Scheme} endpoint = {request.Host}{request.Path}, query = {request.QueryString}, body = {bodyAsText}";
        }
    }
}
 
Program.cs 에 다음 코드 추가
 
using WebApiBasicTutorial.Middleware;
...
app.UseMiddleware<ApiLoggingMiddleware>();
 
 
 
Api Tracer with MediatR using IPipelineBehavior
 
Behaviors 폴더 추가
MediatRLoggingBehavior.cs 추가
using MediatR;
using System.Diagnostics;
using System.Text.Json;
using WebApiBasicTutorial.Logger;

namespace WebApiBasicTutorial.Behaviors
{
    public class MediatRLoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    {
        private readonly IApiLogger _logger;

        public MediatRLoggingBehavior(IApiLogger logger)
        {
            _logger = logger;
        }

        public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
        {
            string requestName = typeof(TRequest).Name;
            string uniqueId = Guid.NewGuid().ToString();
            _logger.LogInformation($"Begin Request Id:{uniqueId}, request name:{requestName},\nRequest={JsonSerializer.Serialize(request, new JsonSerializerOptions { WriteIndented = true })}");
            var timer = new Stopwatch();
            timer.Start();
            var response = next();
            timer.Stop();

            _logger.LogInformation($"End Request Id:{uniqueId}, request name:{requestName},\nResponse={JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = true })}" +
                $"\ntotal elapsed time: {timer.ElapsedMilliseconds}");

            return response;
        }
    }
}
 
 
Program.cs 에 다음 코드 추가
using WebApiBasicTutorial.Middleware;
...
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(MediatRLoggingBehavior<,>));
 
 

10. Add Web Api

Add User
 
Interface 폴더 생성 --> Contract 폴더 생성
 
User.cs 추가
namespace WebApiBasicTutorial.Interface.Contract
{
    public class User
    {
        public string Id { get; set; } = string.Empty;
        public string Name { get; set; } = string.Empty;
        public string Email { get; set; } = string.Empty;
    }
}
 
Command 폴더 생성 
 
AddUser.cs 추가
using MediatR;
using Microsoft.EntityFrameworkCore;
using WebApiBasicTutorial.Infrastructure;
using WebApiBasicTutorial.Interface.Contract;

namespace WebApiBasicTutorial.Command
{
    public class AddUser:IRequest<List<User>>
    {
        public string Id { get; set; } = string.Empty;
        public string Name { get; set; } = string.Empty;
        public string Email { get; set; } = string.Empty;
    }

    public class AddUserHandler : IRequestHandler<AddUser, List<User>>
    {
       private readonly MyDbContext _dbContext;

        public AddUserHandler(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public async Task<List<User>> Handle(AddUser request, CancellationToken cancellationToken)
        {
            _dbContext.Users.Add(new Infrastructure.Models.User()
            {
                Id = request.Id,
                Name = request.Name,
                Email = request.Email
            });


            _dbContext.SaveChanges();

            var users = await _dbContext.Users.Select(u => new User
            {
                Id = u.Id,
                Name = u.Name,
                Email = u.Email
            }).ToListAsync();

            return users;
        }
    }
}
 
 
UserController.cs 로 이동 아래코드 추가
[ProducesResponseType(typeof(List<User>), StatusCodes.Status200OK)]
[HttpPost("")]
public async Task<IActionResult> CreateUser(string id, string name, string email)
{
    if(!ModelState.IsValid)
        return BadRequest(ModelState);

    var user = new AddUser { Id = id, Name = name, Email = email };
    return Ok(await _mediator.Send(user));
}
 

******** 현재 UserController.cs 상태 ********



 
 
 
Update User
 
Command 폴더 이동
 
UpdateUser.cs 추가
using MediatR;
using WebApiBasicTutorial.Infrastructure;
using WebApiBasicTutorial.Interface.Contract;

namespace WebApiBasicTutorial.Command
{
    public class UpdateUser : IRequest<User>
    {
        public string Id { get; set; } = string.Empty;
        public string Name { get; set; } = string.Empty;
        public string Email { get; set; } = string.Empty;
    }

    public class UpdateUserHandler : IRequestHandler<UpdateUser, User>
    {
        private readonly MyDbContext _dbContext;

        public UpdateUserHandler(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public Task<User> Handle(UpdateUser request, CancellationToken cancellationToken)
        {

            var user = _dbContext.Users.Where(u => u.Id == request.Id).FirstOrDefault();

            if (user == null) throw new Exception($"Can not found user, id = {request.Id}");

            user.Name = request.Name;
            user.Email = request.Email;

            _dbContext.Users.Update(user);
            _dbContext.SaveChanges();

            var updateAfterUser = _dbContext.Users.Where(u => u.Id == request.Id).FirstOrDefault();
            if (updateAfterUser == null) throw new Exception($"Can not found user after update user, id = {request.Id}");

            var response = new User
            {
                Id = updateAfterUser.Id,
                Email = updateAfterUser.Email,
                Name = updateAfterUser.Name,
            };

            return Task.FromResult(response);
        }


    }
}
 
UserController.cs 로 이동 아래코드 추가
 
[ProducesResponseType(typeof(User), StatusCodes.Status200OK)]
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser([FromRoute] string id, string name, string email)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);

    var user = new UpdateUser { Id = id, Name = name, Email = email };
    return Ok(await _mediator.Send(user));
}
 
 
Remove User
 
Command 폴더 이동
 
RemoveUser.cs 추가
using MediatR;
using WebApiBasicTutorial.Infrastructure;

namespace WebApiBasicTutorial.Command
{
   
    public class RemoveUser : IRequest
    {
        public string Id { get; set; } = string.Empty;
    }

   

    public class RemoveUserHandler : AsyncRequestHandler<RemoveUser>
    {
        private readonly MyDbContext _dbContext;

        public RemoveUserHandler(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }


        protected override Task Handle(RemoveUser request, CancellationToken cancellationToken)
        {
            var user = _dbContext.Users.Where(u => u.Id == request.Id).FirstOrDefault();

            if (user == null) throw new Exception($"Can not found user, id = {request.Id}");

            _dbContext.Users.Remove(user);
            _dbContext.SaveChanges();

            return Task.CompletedTask;
        }
    }
}
 
UserController.cs 로 이동 아래코드 추가
 
[ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
[HttpDelete("{id}")]
public async Task<IActionResult> RemoveUser(string id)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);

    var user = new RemoveUser { Id = id };
    await _mediator.Send(user);
    return Ok("Success");
}
 
Get Users
 
Command 폴더 이동
 
GetUsers.cs 추가
using MediatR;
using Microsoft.EntityFrameworkCore;
using WebApiBasicTutorial.Infrastructure;
using WebApiBasicTutorial.Interface.Contract;

namespace WebApiBasicTutorial.Command
{
    public class GetUsers : IRequest<List<User>>
    {
    }

    public class GetUsersHandler : IRequestHandler<GetUsers, List<User>>
    {
        private readonly MyDbContext _dbContext;

        public GetUsersHandler(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public async Task<List<User>> Handle(GetUsers request, CancellationToken cancellationToken)
        {
            var users = await _dbContext.Users.Select(u => new User
            {
                Id = u.Id,
                Name = u.Name,
                Email = u.Email
            }).ToListAsync();

            return users;
        }


    }
}
 
UserController.cs 로 이동 아래코드 추가
 
[ProducesResponseType(typeof(List<User>), StatusCodes.Status200OK)]
[HttpGet("")]
public async Task<IActionResult> GetUsers()
{
    return Ok(await _mediator.Send(new GetUsers()));
}
 
 
Get User
 
Command 폴더 이동
 
GetUser.cs 추가
using MediatR;
using Microsoft.EntityFrameworkCore;
using WebApiBasicTutorial.Infrastructure;
using WebApiBasicTutorial.Interface.Contract;

namespace WebApiBasicTutorial.Command
{
    public class GetUser : IRequest<User>
    {
        public string Id { get; set; } = string.Empty;
    }

    public class GetUserHandler : IRequestHandler<GetUser, User>
    {
        private readonly MyDbContext _dbContext;

        public GetUserHandler(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public async Task<User> Handle(GetUser request, CancellationToken cancellationToken)
        {

            var findUsers = await _dbContext.Users.Where(u => u.Id == request.Id)
                .Select(u => new User
                {
                    Id = u.Id,
                    Name = u.Name,
                    Email = u.Email
                })
                .ToListAsync();

            var findUser = findUsers.SingleOrDefault();

            if (findUser == null) throw new Exception($"Can not found user, user id = {request.Id}");

            return findUser;
        }


    }
}
 
UserController.cs 로 이동 아래코드 추가
 
[ProducesResponseType(typeof(User), StatusCodes.Status200OK)]
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(string id)
{
    if(!ModelState.IsValid)
        return BadRequest(ModelState);

    return Ok(await _mediator.Send(new GetUser { Id=id}));
}
 
 
 
 
UserController.cs 현재상태
using MediatR;
using Microsoft.AspNetCore.Mvc;
using WebApiBasicTutorial.Command;
using WebApiBasicTutorial.Interface.Contract;
using WebApiBasicTutorial.Logger;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using WebApiBasicTutorial.Command;
using WebApiBasicTutorial.Interface.Contract;
using WebApiBasicTutorial.Logger;

namespace WebApiBasicTutorial.Controller
{
    [ApiController]
    [Route("[controller]")]
    public class UserController:ControllerBase
    {
        private readonly IApiLogger _logger;
        private readonly IMediator _mediator;

        public UserController(IApiLogger logger, IMediator mediator)
        {
            _logger = logger;
            _mediator = mediator;
        }

        [ProducesResponseType(typeof(List<User>), StatusCodes.Status200OK)]
        [HttpPost("")]
        public async Task<IActionResult> CreateUser(string id, string name, string email)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            var user = new AddUser { Id = id, Name = name, Email = email };
            return Ok(await _mediator.Send(user));
        }

        [ProducesResponseType(typeof(User), StatusCodes.Status200OK)]
        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateUser([FromRoute] string id, string name, string email)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            var user = new UpdateUser { Id = id, Name = name, Email = email };
            return Ok(await _mediator.Send(user));
        }

        [ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
        [HttpDelete("{id}")]
        public async Task<IActionResult> RemoveUser(string id)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            var user = new RemoveUser { Id = id };
            await _mediator.Send(user);
            return Ok("Success");
        }

        [ProducesResponseType(typeof(List<User>), StatusCodes.Status200OK)]
        [HttpGet("")]
        public async Task<IActionResult> GetUsers()
        {
            return Ok(await _mediator.Send(new GetUsers()));
        }

        [ProducesResponseType(typeof(User), StatusCodes.Status200OK)]
        [HttpGet("{id}")]
        public async Task<IActionResult> GetUser(string id)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            return Ok(await _mediator.Send(new GetUser { Id = id }));
        }
    }
}
 
 
Program.cs 현재상태
using MediatR;
using Microsoft.EntityFrameworkCore;
using Serilog;
using WebApiBasicTutorial.Behaviors;
using WebApiBasicTutorial.Helper;
using WebApiBasicTutorial.Infrastructure;
using WebApiBasicTutorial.Injectables;
using WebApiBasicTutorial.Middleware;

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", false, true)
    .AddJsonFile("appsettings.Development.json", optional: true)
    .Build();

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateBootstrapLogger();

try
{
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers();
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    builder.Host.UseSerilog((ctx, lc) => lc.ReadFrom.Configuration(ctx.Configuration));
    builder.Services.AddMediatR(AssemblyHelper.GetAllAssemblies().ToArray());
    builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(MediatRLoggingBehavior<,>));
    var connectionString = builder.Configuration.GetConnectionString("DbServer");
    builder.Services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));

    builder.Services.Scan(scan => scan
                            .FromAssemblies(AssemblyHelper.GetAllAssemblies())
                            .AddClasses(classes => classes.AssignableTo<ITransientService>())
                            .AsImplementedInterfaces()
                            .WithTransientLifetime()
                            .AddClasses(classes => classes.AssignableTo<IScopedService>())
                            .AsImplementedInterfaces()
                            .WithScopedLifetime()
                            .AddClasses(classes => classes.AssignableTo<ISingletonService>())
                            .AsImplementedInterfaces()
                            .WithSingletonLifetime()
                            );

    var app = builder.Build();
    app.UseSwagger();
    app.UseSwaggerUI();
    app.UseMiddleware<ApiLoggingMiddleware>();
    app.MapControllers();
    
    app.Run();
}
catch (Exception ex)
{
    string type = ex.GetType().Name;
    if (type.Equals("StopTheHostException", StringComparison.OrdinalIgnoreCase)) throw;
    Log.Fatal(ex, "Host terminated unexpectedly");
}finally
{
    Log.CloseAndFlush();
}
 
 
실행화면
 
 
 

10. Refactoring with Extension Method

Extensions 폴더 추가
 
IApplicationBuilderExtension.cs 추가
namespace WebApiBasicTutorial.Extensions
{
    public static class IApplicationBuilderExtension
    {
        public static void UseSwaggerAndSwaggerUI(this IApplicationBuilder self)
        {
            self.UseSwagger();
            self.UseSwaggerUI();
        }
    }
}
 
 
IHostBuilderExtension.cs 추가
using Serilog;

namespace WebApiBasicTutorial.Extensions
{
    public static class IHostBuilderExtension
    {
        public static void AddSerilog(this IHostBuilder self)
        {
            self.UseSerilog((ctx, lc) => lc
                .ReadFrom.Configuration(ctx.Configuration));
        }
    }
}
 
 
IServiceCollectionExtension.cs 추가
using MediatR;
using Microsoft.EntityFrameworkCore;
using WebApiBasicTutorial.Behaviors;
using WebApiBasicTutorial.Helper;
using WebApiBasicTutorial.Infrastructure;
using WebApiBasicTutorial.Injectables;

namespace WebApiBasicTutorial.Extensions
{
    public static class IServiceCollectionExtension
    {
        public static void InitControllerAndSwagger(this IServiceCollection self)
        {
            self.AddControllers();
            self.AddEndpointsApiExplorer();
            self.AddSwaggerGen();

        }

        public static void InitScrutor(this IServiceCollection self)
        {
            self.Scan(scan => scan
                                .FromAssemblies(AssemblyHelper.GetAllAssemblies())
                                .AddClasses(classes => classes.AssignableTo<ITransientService>())
                                .AsImplementedInterfaces()
                                .WithTransientLifetime()
                                .AddClasses(classes => classes.AssignableTo<IScopedService>())
                                .AsImplementedInterfaces()
                                .WithScopedLifetime()
                                .AddClasses(classes => classes.AssignableTo<ISingletonService>())
                                .AsImplementedInterfaces()
                                .WithSingletonLifetime()
                                );
        }

        public static void InitMediatR(this IServiceCollection self)
        {
            self.AddMediatR(AssemblyHelper.GetAllAssemblies().ToArray());
            self.AddTransient(typeof(IPipelineBehavior<,>), typeof(MediatRLoggingBehavior<,>));
        }

        public static void AddAccessDb(this IServiceCollection self, string connectionString)
        {
            self.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));
        }
    }
}
 
Program.cs 최종
using Serilog;
using WebApiBasicTutorial.Extensions;
using WebApiBasicTutorial.Middleware;

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", false, true)
    .AddJsonFile("appsettings.Development.json", optional: true)
    .Build();

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateBootstrapLogger();

try
{
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.InitControllerAndSwagger();
    builder.Host.AddSerilog();
    builder.Services.InitMediatR();
    builder.Services.AddAccessDb(builder.Configuration.GetConnectionString("DbServer"));
    builder.Services.InitScrutor();


    var app = builder.Build();
    app.UseSwaggerAndSwaggerUI();
    app.UseMiddleware<ApiLoggingMiddleware>();
    app.MapControllers();

    app.Run();
}
catch (Exception ex)
{
    string type = ex.GetType().Name;
    if (type.Equals("StopTheHostException", StringComparison.OrdinalIgnoreCase)) throw;
    Log.Fatal(ex, "Host terminated unexpectedly");
}finally
{
    Log.CloseAndFlush();
}
 
관련영상
 
 
반응형