I'm learning C#.NET Core and trying to create DTO mapping without using AutoMapper as I'm working on a small project alone and want to understand fundamental before using extra packages, surpringly I could not easily find answer at stackoverflow.com or I may use wrong keyword searching.
BTW, below is my code which I successfully map to EmployeeForShortDto under GetEmployee method. Unfortunately, I don't how to map it under GetAllEmployee just because the return data is a collection, not a single record. Please advice.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NetCoreWebApplication1.Dto;
using NetCoreWebApplication1.Repository;
using NetCoreWebApplication1.Other;
namespace NetCoreWebApplication1.Controller
{
[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
private readonly IMasterRepository _repo;
public EmployeeController(IMasterRepository repo)
{
_repo = repo;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetEmployee(int id)
{
var data = await _repo.GetEmployee(id);
if (data == null) return NotFound();
var dataDto = new EmployeeForShortDto()
{
Id = data.Id,
EmpCode = data.EmpCode,
Fname = data.Fname,
Lname = data.Lname,
Age = NetCoreWebApplication1.Other.Extension.CalcAge(data.DateBirth)
};
return Ok(dataDto);
}
[HttpGet]
public async Task<IActionResult> GetAllEmployee()
{
var data = await _repo.GetAllEmployee();
return Ok(data);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using NetCoreWebApplication1.Models;
namespace NetCoreWebApplication1.Repository
{
public class MasterRepository : IMasterRepository
{
private readonly PrDbContext _context;
public MasterRepository(PrDbContext context)
{
_context = context;
}
// Employee
public async Task<List<Employee>> GetAllEmployee()
{
var data = await _context.Employee.ToListAsync();
return data;
}
public async Task<Employee> GetEmployee(int id)
{
var data = await _context.Employee.FirstOrDefaultAsync(x => x.Id == id);
return data;
}
// Generic methods
public void Add<T>(T entity) where T : class
{
_context.Add(entity);
}
public void Delete<T>(T entity) where T : class
{
_context.Remove(entity);
}
public async Task<bool> SaveAll()
{
return await _context.SaveChangesAsync() > 0;
}
}
}
You can use an extension method to map from your entity type to your DTO type.
public static EmployeeForShortDto ToDto(this Employee employee)
{
if (employee != null)
{
return new EmployeeForShortDto
{
Id = employee.Id,
EmpCode = employee.EmpCode,
Fname = employee.Fname,
Lname = employee.Lname,
Age = NetCoreWebApplication1.Other.Extension.CalcAge(employee.DateBirth)
};
}
return null;
}
And then use where needed.
[HttpGet("{id}")]
public async Task<IActionResult> GetEmployee(int id)
{
var data = await _repo.GetEmployee(id);
if (data == null)
{
return NotFound();
}
return Ok(data.ToDto());
}
[HttpGet]
public async Task<IActionResult> GetAllEmployee()
{
var data = await _repo.GetAllEmployee();
return Ok(data.Select(x => x.ToDto()));
}
thank you for all responses, all are very useful to me. Finally, I end up with solution from @Brad. I also learned how to make a reverse mapping from DTO to a class before adding a record to the database.
I put my code below in case someone want to see. Any comments/suggestions are more than welcome. Thank you.
Extension.cs
using NetCoreWebApplication1.Dto;
using NetCoreWebApplication1.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NetCoreWebApplication1.Other
{
public static class Extension
{
public static EmployeeForShortDto MapToEmployeeForShortDto(this Employee emp)
{
if (emp != null)
{
return new EmployeeForShortDto
{
Id = emp.Id,
EmpCode = emp.EmpCode,
Fname = emp.Fname,
Lname = emp.Lname,
Age = emp.DateBirth.CalcAge()
};
}
return null;
}
public static EmployeeForListDto MapToEmployeeForListDto(this Employee emp)
{
if (emp != null)
{
return new EmployeeForListDto
{
Id = emp.Id,
EmpCode = emp.EmpCode,
Fname = emp.Fname,
Lname = emp.Lname,
Age = emp.DateBirth.CalcAge(),
EntityCode = emp.EntityCode,
IsActive = emp.IsActive
};
}
return null;
}
public static Employee MapFromEmployeeForAddDto(this EmployeeForAddDto emp)
{
if (emp != null)
{
return new Employee
{
EmpCode = emp.EmpCode,
Fname = emp.Fname,
Lname = emp.Lname,
IdCard = emp.IdCard,
IsActive = 1
};
}
return null;
}
public static int CalcAge(this DateTime? dateBirth)
{
if (dateBirth.HasValue)
{
var age = DateTime.Today.Year - dateBirth.Value.Year;
if (dateBirth.Value.AddYears(age) > DateTime.Today) age--;
return age;
}
else
{
return 0;
}
}
}
}
MasterRepository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using NetCoreWebApplication1.Dto;
using NetCoreWebApplication1.Models;
namespace NetCoreWebApplication1.Repository
{
public class MasterRepository : IMasterRepository
{
private readonly PrDbContext _context;
public MasterRepository(PrDbContext context)
{
_context = context;
}
// Employee
public async Task<List<Employee>> GetAllEmployee()
{
var data = await _context.Employee.ToListAsync();
return data;
}
public async Task<Employee> GetEmployee(int id)
{
var data = await _context.Employee.FirstOrDefaultAsync(x => x.Id == id);
return data;
}
public async Task<Employee> AddEmployee(Employee data)
{
await _context.Employee.AddAsync(data);
await _context.SaveChangesAsync();
return data;
}
public async Task<bool> EmployeeExists(string entityCode, string empCode)
{
if (await _context.Employee.AnyAsync(x =>
x.EntityCode == entityCode &&
x.EmpCode == empCode))
return true;
return false;
}
// Generic methods
public void Add<T>(T entity) where T : class
{
_context.Add(entity);
}
public void Delete<T>(T entity) where T : class
{
_context.Remove(entity);
}
public async Task<bool> SaveAll()
{
return await _context.SaveChangesAsync() > 0;
}
}
}
EmployeeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NetCoreWebApplication1.Dto;
using NetCoreWebApplication1.Repository;
using NetCoreWebApplication1.Other;
using NetCoreWebApplication1.Models;
namespace NetCoreWebApplication1.Controller
{
[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
private readonly IMasterRepository _repo;
public EmployeeController(IMasterRepository repo)
{
_repo = repo;
}
[HttpPost("add")]
public async Task<IActionResult> AddEmployee(EmployeeForAddDto emp)
{
if (await _repo.EmployeeExists(emp.EntityCode, emp.EmpCode))
ModelState.AddModelError("Employee", "Employee is duplicate (EntityCode + EmpCode)");
if (!ModelState.IsValid)
return BadRequest(ModelState);
Employee employeeToAdd = emp.MapFromEmployeeForAddDto();
await _repo.AddEmployee(employeeToAdd);
return StatusCode(201);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetEmployee(int id)
{
var data = await _repo.GetEmployee(id);
if (data == null) return NotFound();
return Ok(data.MapToEmployeeForShortDto());
}
[HttpGet]
public async Task<IActionResult> GetAllEmployee()
{
var data = await _repo.GetAllEmployee();
//var dataDto = data.Select(x => x.MapToEmployeeForShortDto());
var dataDto = data.Select(x => x.MapToEmployeeForListDto());
return Ok(dataDto);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With