Search This Blog

2021-03-03

Create a Simple .NET Core Web API Structure

 App.Core Project
















SharedKernel\BaseEntity.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace PairingTest.API.Core.SharedKernel
{
    public abstract class BaseEntity
    {
        [Required]
        [Key]
        public long Id { get; set; }
    }
}

Entities\Question.cs

using PairingTest.API.Core.SharedKernel;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace PairingTest.API.Core.Entities
{
    public class Question : BaseEntity
    {
        [Required]
        public string QuestionnaireTitle { get; set; }
        public List<QuestionOption> QuestionOption { get; set; }
    }
}

Entities\QuestionOption.cs

using PairingTest.API.Core.SharedKernel;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace PairingTest.API.Core.Entities
{
    public class QuestionOption : BaseEntity
    {
        [Required]
        public long QuestionID { get; set; }
        public Question QuestionOptionQuestion { get; set; }
        [Required]
        public string QuestionsText { get; set; }
    }
}

Interfaces\IQuestionnaireService.cs

using PairingTest.API.Core.Entities;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace PairingTest.API.Core.Interfaces
{
    public interface IQuestionnaireService
    {
        Task<List<Question>> GetAllQuestionsWithOptions();
    }
}

Interfaces\IRepository.cs

using PairingTest.API.Core.Entities;
using PairingTest.API.Core.SharedKernel;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace PairingTest.API.Core.Interfaces
{
    public interface IRepository
    {
        T Add<T>(T entity) where T : BaseEntity;
        void Update<T>(T entity) where T : BaseEntity;
        void Delete<T>(T entity) where T : BaseEntity;
        Task<List<Question>> GetAllQuestions();
    }
}

Services\QuestionnaireService.cs

using PairingTest.API.Core.Entities;
using PairingTest.API.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace PairingTest.API.Core.Services
{
    public class QuestionnaireService : IQuestionnaireService
    {
        private IRepository repository;
        public QuestionnaireService(IRepository repos)
        {
            this.repository = repos;
        }
        public async Task<List<Question>> GetAllQuestionsWithOptions()
        {
            return await this.repository.GetAllQuestions();
        }
    }
}

 App.Infrastructure Project















Data\PairingTestDBContext.cs

using Microsoft.EntityFrameworkCore;
using PairingTest.API.Core.Entities;
using PairingTest.API.Infrastructure.DBMapping;
using System;
using System.Collections.Generic;
using System.Text;

namespace PairingTest.API.Infrastructure.Data
{
    public class PairingTestDBContext : DbContext
    {
        public DbSet<Question> Question { get; set; }
        public DbSet<QuestionOption> QuestionOption { get; set; }

        public PairingTestDBContext(DbContextOptions<PairingTestDBContext> options) : base(options)
        {

        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Question>().HasData(
               new { Id =(long) 1, QuestionnaireTitle = "Geography Questions" }
            );
            modelBuilder.Entity<QuestionOption>().HasData(
               new { Id = (long)1, QuestionID = (long)1, QuestionsText = "What is the capital of Cuba?" },
               new { Id = (long)2, QuestionID = (long)1, QuestionsText = "What is the capital of France?" },
               new { Id = (long)3, QuestionID = (long)1, QuestionsText = "What is the capital of Poland?" },
               new { Id = (long)4, QuestionID = (long)1, QuestionsText = "What is the capital of Germany?" }
            );

            new QuestionMap(modelBuilder.Entity<Question>());
            new QuestionOptionMap(modelBuilder.Entity<QuestionOption>());
        }
    }
}

Data\PairingTestRepository.cs

using Microsoft.EntityFrameworkCore;
using PairingTest.API.Core.Entities;
using PairingTest.API.Core.Interfaces;
using PairingTest.API.Core.SharedKernel;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace PairingTest.API.Infrastructure.Data
{
    public class PairingTestRepository : IRepository
    {
        private readonly PairingTestDBContext dbContext;
        public PairingTestRepository(PairingTestDBContext context)
        {
            this.dbContext = context;

            if (this.dbContext.Database.IsSqlServer())
            {
                this.dbContext.Database.Migrate();
            }
        }

        public T Add<T>(T entity) where T : BaseEntity
        {
            this.dbContext.Set<T>().Add(entity);
            this.dbContext.SaveChanges();

            return entity;
        }

        public void Delete<T>(T entity) where T : BaseEntity
        {
            this.dbContext.Set<T>().Remove(entity);
            this.dbContext.SaveChanges();
        }

        public void Update<T>(T entity) where T : BaseEntity
        {
            this.dbContext.Entry(entity).State = EntityState.Modified;
            this.dbContext.SaveChanges();
        }

        public async Task<List<Question>> GetAllQuestions()
        {
            List<Question> lstQuestion = await this.dbContext.Question
                .Include(p=>p.QuestionOption)
                .ToListAsync<Question>();
            return lstQuestion;
        }
    }
}

DBMapping\QuestionMap.cs

using Microsoft.EntityFrameworkCore.Metadata.Builders;
using PairingTest.API.Core.Entities;
using System;
using System.Collections.Generic;
using System.Text;

namespace PairingTest.API.Infrastructure.DBMapping
{
    public class QuestionMap
    {
        public QuestionMap(EntityTypeBuilder<Question> entityBuilder)
        {
            entityBuilder.HasKey(p => p.Id);
            entityBuilder.Property(p => p.QuestionnaireTitle).IsRequired();
        }
    }
}

DBMapping\QuestionOptionMap.cs

using Microsoft.EntityFrameworkCore.Metadata.Builders;
using PairingTest.API.Core.Entities;
using System;
using System.Collections.Generic;
using System.Text;

namespace PairingTest.API.Infrastructure.DBMapping
{
    public class QuestionOptionMap
    {
        public QuestionOptionMap(EntityTypeBuilder<QuestionOption> entityBuilder)
        {
            entityBuilder.HasKey(p => p.Id);
            entityBuilder.Property(p => p.QuestionsText).IsRequired();
        }
    }
}

App.WebAPI Project
















appsettings.Development.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "ConnectionStrings": {
    "TESTDB": "Server=(localdb)\\mssqllocaldb;Database=Test01;Trusted_Connection=True;"
  }
}

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using PairingTest.API.Infrastructure.Data;
using PairingTest.WebApi.Interfaces;
using Microsoft.EntityFrameworkCore;
using PairingTest.API.Core.Interfaces;
using PairingTest.API.Core.Services;

namespace PairingTest.WebApi
{
    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.AddControllers();
            services.AddTransient<IQuestionRepository, QuestionRepository>();

            services.AddSingleton(this.Configuration);
            string connectionString = this.Configuration.GetConnectionString("TESTDB");
            services.AddDbContext<PairingTestDBContext>(options => options.UseSqlServer(connectionString));
            services.AddScoped<IRepository, PairingTestRepository>();

            services.AddTransient<IQuestionnaireService, QuestionnaireService>();           

        }

        // 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.UseHttpsRedirection();
           
            app.UseRouting();

            app.UseAuthorization();

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

Interfaces\IQuestionRepository.cs
namespace PairingTest.WebApi.Interfaces
{
    public interface IQuestionRepository
    {
        Questionnaire GetQuestionnaire();
    }
}

Controllers\QuestionsController.cs

using Microsoft.AspNetCore.Mvc;
using PairingTest.API.Core.Interfaces;
using PairingTest.WebApi.Interfaces;

namespace PairingTest.WebApi.Controllers
{
    [Route("api/[controller]")]
    public class QuestionsController : Controller
    {
        private readonly IQuestionRepository _questionRepository;
        private IQuestionnaireService questionnaireService;
        public QuestionsController(IQuestionRepository questionRepository, IQuestionnaireService _questionnaireService)
        {
            _questionRepository = questionRepository;
            this.questionnaireService = _questionnaireService;
        }

        // GET api/questions
        [HttpGet]
        public Questionnaire Get() //public async Task<IActionResult> Get()
        {
            var x =this.questionnaireService.GetAllQuestionsWithOptions().Result;
            return _questionRepository.GetQuestionnaire();
        }
}
}




No comments: