Cần giúp sửa lỗi code Web API

Chào mn ạ. Nhờ mn sửa giúp em lỗi này với. Lúc em chạy api thử trên local host thì chuỗi JSON nó trả về bị null. Em vẫn chưa tìm được lỗi sai ở đâu ạ.

Employee.cs

namespace MyWebApiApp.Domain.Models
{

    public class Employee
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public string? ■■■ { get; set; }

        public IList<Machine>? Machines { get; set; } = new List<Machine>();
    }
}

Machine.cs

namespace MyWebApiApp.Domain.Models
{

    public class Machine
    {
        public int Id { get; set; }
        public bool IsActive { get; set; }
        public string? Name { get; set; }
        public string? Origin { get; set; } 

        public Employee? Employee { get; set; }
        public int EmployeeId { get; set; }
    }
}

EmployeeController.cs

namespace MyWebApiApp.Controllers
{

    [Route("API/[controller]")]
    public class EmployeeController : Controller
    {
        private readonly IEmployeeService _employeeService;
        private readonly IMapper _mapper;
        public EmployeeController (IEmployeeService employeeService, IMapper mapper)
        {
            _employeeService = employeeService;
            _mapper = mapper;
        }

        [HttpGet]
        public async Task<IEnumerable<EmployeeResource>> GetAllEmployees()
        {
            var employees = await _employeeService.GetAllEmployees();
            var employeeResources = _mapper.Map<IEnumerable<Employee>, IEnumerable<EmployeeResource>>(employees);

            return employeeResources;
        }
}

MachineController.cs

namespace MyWebApiApp.Controllers
{

    [Route("API/[controller]")]
    public class MachineController : Controller
    {
        private readonly IMachineService _machineService;
        private readonly IMapper _mapper;
        public MachineController (IMachineService machineService, IMapper mapper)
        {
            _machineService = machineService;
            _mapper = mapper;
        }

        [HttpGet]
        public async Task<IEnumerable<MachineResource>> GetAllMachines()
        {
            IEnumerable<Machine> machines = await _machineService.GetAllMachines();
            var machineResources = _mapper.Map<IEnumerable<Machine>, IEnumerable<MachineResource>>(machines);

            return machineResources;
        }

**IEmployeeService.cs**
namespace MyWebApiApp.Domain.Persistence.IServices
{

    public interface IEmployeeService
    {
        Task<IEnumerable<Employee>> GetAllEmployees();
    }
}

IMachineService.cs

namespace MyWebApiApp.Domain.IServices
{

    public interface IMachineService
    {
        public Task<IEnumerable<Machine>> GetAllMachines();
    }
}

EmployeeService.cs

namespace MyWebApiApp.Services
{

    public class EmployeeService : IEmployeeService
    {
        private readonly IEmployeeRepository _employeeRepository;
        public EmployeeService(IEmployeeRepository employeeRepository)
        {
            _employeeRepository = employeeRepository;
        }
        public async Task<IEnumerable<Employee>> GetAllEmployees()
        {
            return await _employeeRepository.GetAllEmployees();
        }
    }
}

MachineService.cs

namespace MyWebApiApp.Services
{

    public class MachineService : IMachineService
    {
        private readonly IMachineRepository _machineRepository;
        public MachineService(IMachineRepository machineRepository)
        {
            _machineRepository = machineRepository;
        }
        public async Task<IEnumerable<Machine>> GetAllMachines()
        {
            return await _machineRepository.GetAllMachines();
        }
    }
}

IEmployeeRepository.cs

namespace MyWebApiApp.Domain.IRepository
{

    public interface IEmployeeRepository
    {
        Task <IEnumerable<Employee>> GetAllEmployees();
    }
}

IMachineRepository.cs

namespace MyWebApiApp.Domain.IRepository
{

    public interface IMachineRepository
    {
        Task<IEnumerable<Machine>> GetAllMachines();
    }
}

BaseRepository.cs

namespace MyWebApiApp.Domain.Persistence.Repositories
{

    public class BaseRepository
    {
        protected readonly MyDbContext _context;
        public BaseRepository (MyDbContext context)
        {
            _context = context;
        }
    }
}

EmployeeRepository.cs

namespace MyWebApiApp.Domain.Persistence.Repositories
{

    public class EmployeeRepository : BaseRepository, IEmployeeRepository
    {
        public EmployeeRepository (MyDbContext context) : base(context) { }
        async Task<IEnumerable<Employee>> IEmployeeRepository.GetAllEmployees()
        {
            return await _context.Employees.ToListAsync<Employee>();
        }
    }
}

MachineRepository.cs

namespace MyWebApiApp.Domain.Persistence.Repositories
{

    public class MachineRepository : BaseRepository, IMachineRepository
    {
        public MachineRepository(MyDbContext context) : base(context)
        {
        }
        public async Task<IEnumerable<Machine>> GetAllMachines()
        {
            return await _context.Machines.Include(m => m.Employee).ToListAsync();
        }
    }
}

ModelToResource.cs

namespace MyWebApiApp.Mapping
{

    public class ModelToResource : Profile
    {
        public ModelToResource()
        {
            CreateMap<Employee, EmployeeResource>();
            CreateMap<Machine, MachineResource>();
        }
    }
}

EmployeeResource.cs

namespace MyWebApiApp.Resources
{

    public class EmployeeResource
    {
        public int Id { get; set; }
        public string? Name { get; set; }
    }
}

MachineResource.cs

namespace MyWebApiApp.Resources
{

    public class MachineResource
    {
        public int Id { get; set; }
        public bool IsActive { get; set; }
        public EmployeeResource? EmployeeResource { get; set; } 
    }
}

MyDbContext.cs

namespace MyWebApiApp.Domain.Persistence.Contexts
{

    public class MyDbContext : DbContext
    {
        public DbSet<Employee> Employees { get; set; }
        public DbSet<Machine> Machines { get; set; }
        public MyDbContext (DbContextOptions<MyDbContext> options) : base (options)
        {
        }
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<Employee>().ToTable("Employees");
            builder.Entity<Employee>().HasKey(e => e.Id);
            builder.Entity<Employee>().Property(e => e.Id).IsRequired().ValueGeneratedOnAdd();
            builder.Entity<Employee>().Property(e => e.Name).IsRequired().HasMaxLength(50);
            builder.Entity<Employee>().Property(e => e.■■■).IsRequired().HasMaxLength(5);
            builder.Entity<Employee>().HasMany<Machine>(e => e.Machines).WithOne(e => e.Employee).HasForeignKey(e => e.EmployeeId);
            builder.Entity<Employee>().HasData(
                new Employee { Id = 1, Name = "Nguyen Van A", ■■■ = "Male" }
                );

            builder.Entity<Machine>().ToTable("Machines");
            builder.Entity<Machine>().HasKey(m => m.Id);
            builder.Entity<Machine>().Property(m => m.Id).IsRequired().ValueGeneratedOnAdd();
            builder.Entity<Machine>().Property(m => m.Name).IsRequired().HasMaxLength(30);
            builder.Entity<Machine>().Property(m => m.IsActive).IsRequired();
            builder.Entity<Machine>().Property(m => m.Origin).IsRequired().HasMaxLength(30);
            builder.Entity<Machine>().HasData(
                new Machine { Id = 1, IsActive = true, Name = "Máy 1", Origin = "China", EmployeeId = 1 }
                );
        } 
    }
}

Program.cs (Main)

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddAutoMapper(typeof(Program).Assembly);
builder.Services.AddScoped<IEmployeeRepository, EmployeeRepository>();
builder.Services.AddScoped<IMachineRepository, MachineRepository>();
builder.Services.AddScoped<IEmployeeService, EmployeeService>();
builder.Services.AddScoped<IMachineService, MachineService>();
builder.Services.AddDbContext<MyDbContext>(opt =>
    opt.UseSqlServer(builder.Configuration.GetConnectionString("Connect")));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

GlobalUse.cs

global using Microsoft.AspNetCore.Mvc;
global using MyWebApiApp.Domain.Models;
global using MyWebApiApp.Domain.Persistence.IServices;
global using MyWebApiApp.Domain.IServices;
global using Microsoft.EntityFrameworkCore;
global using MyWebApiApp.Domain.IRepository;
global using MyWebApiApp.Domain.Persistence.Repositories;
global using MyWebApiApp.Services;
global using MyWebApiApp.Domain.Persistence.Contexts;
global using MyWebApiApp.Resources;
global using AutoMapper;

Nguyên nhân do mapper bạn chưa config
Ở MachineResource , EmployeeResource không dc map với property nào của Machine.
Automap chưa thông minh tới mức map với Employee được, bạn phải config bằng tay

3 Likes

Cho em hỏi là mình config như nào vậy ạ?

Em có thử chuyển cái property EmployeeResource bên class MachineResource thành Employee thôi thì nó map được ạ

Bản chất automap mặc định là

// objectA: classA;==> objectB: classB
for each (property in classA.properties) {
  valueA = classA.GetProperty(property).GetValue(objectA)
  classB.GetProperty(property ).SetValue(objectB, null);
}

Nếu 2 property khác tên nhau bạn cần thêm code để automapper biết cần map tới field nào
https://docs.automapper.org/en/latest/Attribute-mapping.html
hoặc
https://docs.automapper.org/en/latest/Mapping-inheritance.html

3 Likes

Em cảm ơn anh nhiều ạ

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?