ASP.Net Core 3.1 Repository Pattern and Unit of Work Using Dapper

In this article I will create a web api using ASP.Net Core 3.1 and instead of using the Entity Framework which I usually do. I will try to use Dapper. We will also use Repository pattern and Unit of Work to manage our data.

Then later, I will show you how to use the repository pattern and unit of work in CQRS with MediatR.

We will create a web api to manage task and we will store it in SQL Server. To start the development, create a database in SQL Server called TaskManagementDb.

Then execute this query to create our table.

CREATE TABLE [dbo].[Tasks1](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Name] [nvarchar](50) NOT NULL,
	[Description] [nvarchar](50) NOT NULL,
	[Status] [int] NOT NULL,
	[DueDate] [datetime] NOT NULL,
	[DateCreated] [datetime] NOT NULL,
	[DateModified] [datetime] NULL
)

After creating the database, create a new Asp.Net Core Web Application project and call it TaskManagementApp.Api then select API for project template.

Advertisements

We will follow clean architecture for our code structure. Create a .Net Standard Class Library project for the following:

  • TaskManagementApp.Core
  • TaskManagementApp.Application
  • TaskManagementApp.Infrastructure

The TaskManagementApp.Core will contain our entities. Add a new folder called Entities then create a new class inside the Entities folder and call it Task.

using System;
using TaskManagementApp.Core.Enums;

namespace TaskManagementApp.Core.Entities
{
    public class Task
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public TaskStatus Status { get; set; }
        public DateTime DueDate { get; set; }
        public DateTime DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
    }
}

We will use enum to determine the status of the task. Create a new folder in TaskManagementApp.Core and call it Enums. Then in Enums folder create a new .cs file called TaskStatus.

namespace TaskManagementApp.Core.Enums
{
    public enum TaskStatus
    {
        Created,
        Active,
        Done
    }
}

Build the project then we are done with our core layer.

Advertisements

In TaskManagementApp.Application add reference to TaskManagementApp.Core.

Create a folder called Interfaces. Then in Interfaces folder create file called IGenericRepository.cs

using System.Collections.Generic;
using System.Threading.Tasks;

namespace TaskManagementApp.Application.Interfaces
{
    public interface IGenericRepository<T> where T : class
    {
        Task<T> Get(int id);
        Task<IEnumerable<T>> GetAll();
        Task<int> Add(T entity);
        Task<int> Delete(int id);
        Task<int> Update(T entity);
    }
}

Then create an interface for TaskRepository that implements IGenericRepository and call it ITaskRepository

using TaskManagementApp.Core.Entities;

namespace TaskManagementApp.Application.Interfaces
{
    public interface ITaskRepository: IGenericRepository<Task>
    {
    }
}

Then create an interface for the unit of work. Call it IUnitoOfWork

namespace TaskManagementApp.Application.Interfaces
{
    public interface IUnitOfWork
    {
        ITaskRepository Tasks { get; }
    }
}

Build the project then we are done with our application layer.

Advertisements

In TaskManagementApp.Infrastruture add a reference to TaskManagementApp.Application.

The infrastructure layer is responsible in implementing our interfaces and connecting to the database. We will use Dapper as ORM and SQL Server as database, so we need to install some nuget packages.

  • Dapper
  • System.Data.SqlClient
  • Microsoft.Extensions.Configuration
  • Microsoft.Extensions.DependencyInjection

Then create a new folder called Repositories. Inside the Repositories folder add a new class for TaskRepository. The TaskRepository will implement the interface ITaskRepository that we did in our application layer.

using Dapper;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
using TaskManagementApp.Application.Interfaces;

namespace TaskManagementApp.Infrastructure.Repositories
{
    public class TaskRepository : ITaskRepository
    {
        private readonly IConfiguration _configuration;

        public TaskRepository(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        public async Task<int> Add(Core.Entities.Task entity)
        {
            entity.DateCreated = DateTime.Now;
            var sql = "INSERT INTO Tasks (Name, Description, Status, DueDate, DateCreated) Values (@Name, @Description, @Status, @DueDate, @DateCreated);";
            using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
            {
                connection.Open();
                var affectedRows = await connection.ExecuteAsync(sql, entity);
                return affectedRows;
            }
        }

        public async Task<int> Delete(int id)
        {
            var sql = "DELETE FROM Tasks WHERE Id = @Id;";
            using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
            {
                connection.Open();
                var affectedRows = await connection.ExecuteAsync(sql, new { Id = id });
                return affectedRows;
            }
        }

        public async Task<Core.Entities.Task> Get(int id)
        {
            var sql = "SELECT * FROM Tasks WHERE Id = @Id;";
            using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
            {
                connection.Open();
                var result = await connection.QueryAsync<Core.Entities.Task>(sql, new { Id = id });
                return result.FirstOrDefault();
            }
        }

        public async Task<IEnumerable<Core.Entities.Task>> GetAll()
        {
            var sql = "SELECT * FROM Tasks;";
            using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
            {
                connection.Open();
                var result = await connection.QueryAsync<Core.Entities.Task>(sql);
                return result;
            }
        }

        public async Task<int> Update(Core.Entities.Task entity)
        {
            entity.DateModified = DateTime.Now;
            var sql = "UPDATE Tasks SET Name = @Name, Description = @Description, Status = @Status, DueDate = @DueDate, DateModified = @DateModified WHERE Id = @Id;";
            using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
            {
                connection.Open();
                var affectedRows = await connection.ExecuteAsync(sql, entity);
                return affectedRows;
            }
        }
    }
}

Then let’s implement our IUnitOfWork. Create a new class and call it UnitOfWork.

using TaskManagementApp.Application.Interfaces;

namespace TaskManagementApp.Infrastructure.Repositories
{
    public class UnitOfWork : IUnitOfWork
    {
        public UnitOfWork(ITaskRepository taskRepository)
        {
            Tasks = taskRepository;
        }
        public ITaskRepository Tasks { get; }
    }
}

We will not directly register the binding of our interfaces and concrete class in the starup file of TaskManagementApp.Api instead we will create a static file in infrastructure layer that we can use to register the bindings from infrastructure to our api.

In TaskManagementApp.Infrastructure create a new file called DependencyInjection.cs

using Microsoft.Extensions.DependencyInjection;
using TaskManagementApp.Application.Interfaces;
using TaskManagementApp.Infrastructure.Repositories;

namespace TaskManagementApp.Infrastructure
{
    public static class DependencyInjection
    {
        public static IServiceCollection AddInfrastructure(this IServiceCollection services)
        {
            services.AddTransient<ITaskRepository, TaskRepository>();
            services.AddTransient<IUnitOfWork, UnitOfWork>();
            return services;
        } 
    }
}

Build the project then we can now go to our api.

Advertisements

In TaskManagementApp.Api add reference to TaskManagementApp.Application and TaskManagementApp.Infrastructure.

Then update the file Startup.cs to register the services from TaskManagementApp.Infrastructure. Update the code in ConfigureServices and resolve the missing dependency.

public void ConfigureServices(IServiceCollection services)
        {
            services.AddInfrastructure();
            services.AddControllers();
        }

Then open appsettings.json to add the connection string.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TaskManagementDb;Trusted_Connection=True;MultipleActiveResultSets=true;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Now, we can use our TaskRepository and UnitOfWork in our code to connect to the database.

Advertisements

Now, we will implement CQRS with MediatR to create, update, delete and get our data.

In TaskManagementApp.Application install the following nuget packages

  • AutoMapper
  • AutoMapper.Extensions.Microsoft.DependencyInjection
  • FluentValidation
  • FluentValidation.DependencyInjectionExtensions
  • MediatR.Extensions.Microsoft.DependencyInjection

Then create a folder called Common in TaskManagementApp.Application. Inside the common folder add a folder called Behaviors.

In the Behaviors folder, we will place all PipelineBehavior that we want to add in MediatR. In this article, we will add FluentValidation in MediatR pipeline.

Add a new class called ValidationBehavior

using FluentValidation;
using MediatR;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace TaskManagementApp.Application.Common.Behaviors
{
    public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
    {
        private readonly IEnumerable<IValidator<TRequest>> _validators;

        public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
        {
            _validators = validators;
        }
        public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
        {
            var context = new ValidationContext(request);
            var failures = _validators
                .Select(v => v.Validate(context))
                .SelectMany(result => result.Errors)
                .Where(f => f != null)
                .ToList();

            if(failures.Count != 0)
            {
                throw new ValidationException(failures);
            }

            return next();
        }
    }
}
Advertisements

We need to register MediatR, FluentValidation and AutoMapper in Startup services and just like what we did in Infrastructure layer. We will also handle the registration inside the Application layer.

In TaskManagementApp.Application add a new class called DependencyInjection.

using AutoMapper;
using FluentValidation;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using TaskManagementApp.Application.Common.Behaviors;

namespace TaskManagementApp.Application
{
    public static class DependencyInjection
    {
        public static IServiceCollection AddApplication(this IServiceCollection services)
        {
            services.AddMediatR(Assembly.GetExecutingAssembly());
            services.AddAutoMapper(Assembly.GetExecutingAssembly());
            services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
            services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
            return services;
        }
    }
}

Then go to Starup.cs file in TaskManagementApp.Api to register the services in Application layer. Update the ConfigureServices method of Startup class

public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplication();
            services.AddInfrastructure();
            services.AddControllers();
        }
Advertisements

Now back to TaskManagementApp.Applicaiton. Create a new folder called Tasks. We will put all business logic related to tasks inside this folder.

Inside the Tasks folder add a new folder called Commands. Then inside the Commands folder, add a new class called CreateTaskCommand.

using MediatR;
using System;
using TaskManagementApp.Core.Enums;

namespace TaskManagementApp.Application.Tasks.Commands
{
    public class CreateTaskCommand : IRequest<int>
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public TaskStatus Status { get; set; }
        public DateTime DueDate { get; set; }
    }
}

The CreateTaskCommand is actually a request that will be handled by MediatR. The int in IReqest<int> is the expected result of this request.

The properties in CreateTaskCommand are the payloads that are needed for this request. In this case we need the Name, descipription, Status and DueDate to create the Task.

Every request needs a handler that will handle the request. Inside the Tasks folder create a new folder called Handlers. Then inside the Handlers folder create a new class called CreateTaskCommandHandler

using AutoMapper;
using MediatR;
using System.Threading;
using System.Threading.Tasks;
using TaskManagementApp.Application.Interfaces;
using TaskManagementApp.Application.Tasks.Commands;

namespace TaskManagementApp.Application.Tasks.Handlers
{
    public class CreateTaskCommandHandler : IRequestHandler<CreateTaskCommand, int>
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IMapper _mapper;

        public CreateTaskCommandHandler(IUnitOfWork unitOfWork, IMapper mapper)
        {
            _unitOfWork = unitOfWork;
            _mapper = mapper;
        }
        public async Task<int> Handle(CreateTaskCommand request, CancellationToken cancellationToken)
        {
            var result = await _unitOfWork.Tasks.Add(_mapper.Map<TaskManagementApp.Core.Entities.Task>(request));
            return result;
        }
    }
}

The CreateTaskCommandHandler implements the IRequestHandler<CreateTaskCommand, int>. The CreateTaskCommand is the request and then the int is the output.

Then in Handle method, we add the code that we want to execute once the MediatR receives a request of CreateTaskCommand. In this case we want it to be added in our database.

Advertisements

We use AutoMapper here to automatically map the properties of the CreateTaskCommand to Task. But for it to work, we need to register the Mapping Profile in automapper.

Inside the Tasks folder create a new folder called MappingProfiles. The inside the MappingProfiles add a new class called TaskMappingProfile

using AutoMapper;
using TaskManagementApp.Application.Tasks.Commands;
using TaskManagementApp.Application.Tasks.Dto;
using TaskManagementApp.Core.Entities;

namespace TaskManagementApp.Application.Tasks.MappingProfiles
{
    public class TaskMappingProfile: Profile
    {
        public TaskMappingProfile()
        {
            CreateMap<CreateTaskCommand, Task>();
        }
    }
}

Now we can use the CreateTaskCommand to create a Task, but it does not have any validation on it. To add a validation, create a new folder inside the Tasks folder and call it Validators. Inside the Validators folder create a new class called CreateTaskCommandValidator

using FluentValidation;
using TaskManagementApp.Application.Tasks.Commands;

namespace TaskManagementApp.Application.Tasks.Validators
{
    public class CreateTaskCommandValidator: AbstractValidator<CreateTaskCommand>
    {
        public CreateTaskCommandValidator()
        {
            RuleFor(t => t.Name).NotEmpty();
            RuleFor(t => t.Description).NotEmpty();
            RuleFor(t => t.Status).NotNull();
            RuleFor(t => t.DueDate).NotNull();
        }
    }
}

The CreateTaskCommandValidator will inherit the AbstractValidator. We pass the class that needs to be validated inside the <> in AbstractValidator. Then we set the validation rules inside the constructor.

Advertisements

Now, let’s add the command for UpdatetaskCommand. We will follow same approach as the one we did in CreateTaskCommand.

Create a new class in Commands folder and call it UpdateTaskCommand

using MediatR;
using System;
using System.Threading.Tasks;

namespace TaskManagementApp.Application.Tasks.Commands
{
    public class UpdateTaskCommand : IRequest<int>
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public TaskStatus Status { get; set; }
        public DateTime DueDate { get; set; }
    }
}

Then create a handler in Handlers folder. Call it UpdateTaskCommandHandler

using AutoMapper;
using MediatR;
using System.Threading;
using System.Threading.Tasks;
using TaskManagementApp.Application.Interfaces;
using TaskManagementApp.Application.Tasks.Commands;

namespace TaskManagementApp.Application.Tasks.Handlers
{
    public class UpdateTaskCommandHandler : IRequestHandler<UpdateTaskCommand, int>
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IMapper _mapper;

        public UpdateTaskCommandHandler(IUnitOfWork unitOfWork, IMapper mapper)
        {
            _unitOfWork = unitOfWork;
            _mapper = mapper;
        }
        public async Task<int> Handle(UpdateTaskCommand request, CancellationToken cancellationToken)
        {
            var result = await _unitOfWork.Tasks.Update(_mapper.Map<TaskManagementApp.Core.Entities.Task>(request));
            return result;
        }
    }
}

Create mapping in TaskMappingProfile.

using AutoMapper;
using TaskManagementApp.Application.Tasks.Commands;
using TaskManagementApp.Application.Tasks.Dto;
using TaskManagementApp.Core.Entities;

namespace TaskManagementApp.Application.Tasks.MappingProfiles
{
    public class TaskMappingProfile: Profile
    {
        public TaskMappingProfile()
        {
            CreateMap<CreateTaskCommand, Task>();
            CreateMap<UpdateTaskCommand, Task>();
        }
    }
}

Then create a validator in Validators folder called UpdateTaskCommandValidator

using FluentValidation;
using TaskManagementApp.Application.Tasks.Commands;

namespace TaskManagementApp.Application.Tasks.Validators
{
    public class UpdateTaskCommandValidator : AbstractValidator<UpdateTaskCommand>
    {
        public UpdateTaskCommandValidator()
        {
            RuleFor(t => t.Name).NotEmpty();
            RuleFor(t => t.Description).NotEmpty();
            RuleFor(t => t.Status).NotNull();
            RuleFor(t => t.DueDate).NotNull();
        }
    }
}
Advertisements

Now let’s do the delete Command. Create a new class in Commands folder called DeleteTaskCommand

using MediatR;

namespace TaskManagementApp.Application.Tasks.Commands
{
    public class DeleteTaskCommand: IRequest<int>
    {
        public int Id { get; set; }
    }
}

Then add the handler in Handlers folder. Call it DeleteTaskCommandHandler

using MediatR;
using System.Threading;
using System.Threading.Tasks;
using TaskManagementApp.Application.Interfaces;
using TaskManagementApp.Application.Tasks.Commands;

namespace TaskManagementApp.Application.Tasks.Handlers
{
    public class DeleteTaskCommandHandler : IRequestHandler<DeleteTaskCommand, int>
    {
        private readonly IUnitOfWork _unitOfWork;

        public DeleteTaskCommandHandler(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }
        public async Task<int> Handle(DeleteTaskCommand request, CancellationToken cancellationToken)
        {
            var result = await _unitOfWork.Tasks.Delete(request.Id);
            return result;
        }
    }
}

That’s all for our delete command.

Now let’s do the query. Create a folder in Tasks folder and call it Queries. Inside the Queries folder create a new class called GetAllTasksQuery

using MediatR;
using System.Collections.Generic;
using TaskManagementApp.Application.Tasks.Dto;

namespace TaskManagementApp.Application.Tasks.Queries
{
    public class GetAllTasksQuery: IRequest<List<TaskDto>>
    {
    }
}

We will not going to output the Task from our Core, instead we will create a dto. Create a new folder inside the Tasks folder then call it Dto.

Inside the Dto create a new class called TaskDto

using System;
using TaskManagementApp.Core.Enums;

namespace TaskManagementApp.Application.Tasks.Dto
{
    public class TaskDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public TaskStatus Status { get; set; }
        public DateTime DueDate { get; set; }
        public DateTime DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
    }
}

Now create a handler in Handlers folder. Call it GetAllTasksQueryHandler

using AutoMapper;
using MediatR;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using TaskManagementApp.Application.Interfaces;
using TaskManagementApp.Application.Tasks.Dto;
using TaskManagementApp.Application.Tasks.Queries;

namespace TaskManagementApp.Application.Tasks.Handlers
{
    public class GetAllTasksQueryHandler : IRequestHandler<GetAllTasksQuery, List<TaskDto>>
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IMapper _mapper;

        public GetAllTasksQueryHandler(IUnitOfWork unitOfWork, IMapper mapper)
        {
            _unitOfWork = unitOfWork;
            _mapper = mapper;
        }
        public async Task<List<TaskDto>> Handle(GetAllTasksQuery request, CancellationToken cancellationToken)
        {
            var result = await _unitOfWork.Tasks.GetAll();
            return _mapper.Map<List<TaskDto>>(result.ToList());
        }
    }
}

Then add mapping for Task to TaskDto in TaskMappingProfile

using AutoMapper;
using TaskManagementApp.Application.Tasks.Commands;
using TaskManagementApp.Application.Tasks.Dto;
using TaskManagementApp.Core.Entities;

namespace TaskManagementApp.Application.Tasks.MappingProfiles
{
    public class TaskMappingProfile: Profile
    {
        public TaskMappingProfile()
        {
            CreateMap<CreateTaskCommand, Task>();
            CreateMap<UpdateTaskCommand, Task>();
            CreateMap<Task, TaskDto>();
        }
    }
}

Next add a query to get a specific Task by Id. Add a new class in Queries folder and call it GettaskByIdQuery

using MediatR;
using TaskManagementApp.Application.Tasks.Dto;

namespace TaskManagementApp.Application.Tasks.Queries
{
    public class GetTaskByIdQuery: IRequest<TaskDto>
    {
        public int Id { get; set; }
    }
}

Then create the handler in Handlers folder and call it GetTaskByIdQueryHandler

using AutoMapper;
using MediatR;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TaskManagementApp.Application.Interfaces;
using TaskManagementApp.Application.Tasks.Dto;
using TaskManagementApp.Application.Tasks.Queries;

namespace TaskManagementApp.Application.Tasks.Handlers
{
    public class GetTaskByIdQueryHandler : IRequestHandler<GetTaskByIdQuery, TaskDto>
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IMapper _mapper;

        public GetTaskByIdQueryHandler(IUnitOfWork unitOfWork, IMapper mapper)
        {
            _unitOfWork = unitOfWork;
            _mapper = mapper;
        }
        public async Task<TaskDto> Handle(GetTaskByIdQuery request, CancellationToken cancellationToken)
        {
            var result = await _unitOfWork.Tasks.Get(request.Id);
            return _mapper.Map<TaskDto>(result);
        }
    }
}
Advertisements

Now let’s create our controller for Task api. In TaskManagementApp.API right click to Controllers folder then select add then controller. Select the API Controller Empty and call it ApiController

using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;

namespace TaskManagementApp.Api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ApiController : ControllerBase
    {
        private IMediator _mediator;
        protected IMediator Mediator => _mediator ??= HttpContext.RequestServices.GetService<IMediator>();
    }
}

This will be the base controller for all controllers that will use MediatR.

Now create the controller for tasks. add a new controller called TasksController.

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using TaskManagementApp.Application.Tasks.Commands;
using TaskManagementApp.Application.Tasks.Dto;
using TaskManagementApp.Application.Tasks.Queries;

namespace TaskManagementApp.Api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TasksController : ApiController
    {
        [HttpPost]
        public async Task<ActionResult<int>> Create(CreateTaskCommand command)
        {
            return await Mediator.Send(command);
        }

        [HttpGet]
        public async Task<ActionResult<List<TaskDto>>> GetAll()
        {
            return await Mediator.Send(new GetAllTasksQuery());
        }

        [HttpGet("/{id}")]
        public async Task<ActionResult<TaskDto>> Get(int id)
        {
            return await Mediator.Send(new GetTaskByIdQuery { Id = id });
        }

        [HttpPut]
        public async Task<ActionResult<int>> Update(UpdateTaskCommand command)
        {
            return await Mediator.Send(command);
        }

        [HttpDelete]
        public async Task<ActionResult<int>> Delete(int id)
        {
            return await Mediator.Send(new DeleteTaskCommand { Id = id });
        }
    }
}

In our controller, we only need to send the request in MediatR and then MediatR will look for what handler need to be executed for the request.

Advertisements

Now we are done with our api. To test our API let’s add swagger. Install NSwag.AspNetCore from nuget packages in TaskManagementApp.Api.

Then Update the Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TaskManagementApp.Application;
using TaskManagementApp.Infrastructure;

namespace TaskManagementApp.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.AddApplication();
            services.AddInfrastructure();
            services.AddControllers();
            services.AddOpenApiDocument(config =>
            {
                config.Title = "Task Management App APIP";
            });
        }

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

            app.UseOpenApi();
            app.UseSwaggerUi3();

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

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

Now run the application. Then go to

https://localhost:<port_number>/swagger

Then you can use this page to interact and test your api.

Advertisements

Source Code: https://github.com/alexcalingasan/TaskManagementApp

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s