Я лично делаю следующее Для частичного обновления объекта:
Если я не хочу отправлять всю модель в действие для изменения всего объекта, я бы сделал конечную точку (действие API), которая частично обновляет объект и вернуть код состояния успеха вместо просмотра. Я бы использовал запрос ajax к конечной точке для изменения объекта без обновления страницы.
Это мой код для частичного обновления объекта Employee
:
Employee.cs
public class Employee
{
public int Id { get; set; }
[Required(ErrorMessage ="Employee name is a required field.")]
[MaxLength(30,ErrorMessage ="Maximum length for the Name is 30 chrachters.")]
public string Name { get; set; }
[Required(ErrorMessage = "Age is a required field.")]
public int Age{ get; set; }
[Required(ErrorMessage = "Position is a required field.")]
[MaxLength(20, ErrorMessage = "Maximum length for the Position is 20 chrachters.")]
public string Position { get; set; }
public int CompanyId { get; set; }
public Company Company { get; set; }
}
EmployeeUpdateDto.cs
public class EmployeeUpdateDto
{
[Required(ErrorMessage = "Employee name is required")]
[MaxLength(30, ErrorMessage = "Maximum length for the Name is 30 characters")]
public string Name { get; set; }
[Range(18, int.MaxValue, ErrorMessage = "Minimum age must be 18")]
public int Age { get; set; }
[Required(ErrorMessage = "Employee position is required")]
[MaxLength(20, ErrorMessage = "Maximum length for the Position is 20 characters")]
public string Position { get; set; }
}
Controller.cs
public class EmployeesController : ControllerBase
{
private IRepositoryManager _repository;
private ILoggerManager _logger;
private IMapper _mapper;
public EmployeesController(IRepositoryManager repository, ILoggerManager logger, IMapper mapper)
{
_repository = repository;
_logger = logger;
_mapper = mapper;
}
[HttpPatch("{id}")]
public async Task<IActionResult> PartiallyUpdateEmployee(int id, JsonPatchDocument<EmployeeUpdateDto> employeePatches)
{
if (employeePatches is null)
{
_logger.LogError("JsonPatchDocument object sent from client is null");
return BadRequest();
}
var employeeEntity = await _repository.EmployeeRepository.GetEmployeeAsync(employeeId, trackChanges:true);
if (employeeEntity null)
{
_logger.LogInfo($"Employee with id {id} doesn't exist in the database.");
return NotFound();
}
var employeeUpdateDto = _mapper.Map<EmployeeUpdateDto>(employeeEntity);
employeePatches.ApplyTo(employeeUpdateDto, ModelState);
TryValidateModel(employeeUpdateDto);
if (!ModelState.IsValid)
{
_logger.LogError("invalid model state for the patch document");
return UnprocessableEntity(ModelState);
}
_mapper.Map(employeeUpdateDto, employeeEntity);
await _repository.SaveAsync();
return NoContent();
}
//other action methods
}
Вы должны отправить тело запроса в следующем стандартном формате патча (json):
[
{ "op": "replace", "path": "/name", "new_name": "new name" },
{ "op": "remove", "path": "/position" }
]
Вот и все. приведенный выше пример запроса изменит имя сотрудника на «new_name» и установит для Position значение по умолчанию (в данном случае null).
В приведенном выше примере для работы требуются следующие предварительные условия:
Microsoft.AspNetCore.JsonPatch to support JsonPatchDocument
type.
Microsoft.AspNetCore.Mvc.NewtonsoftJson to support mapping request to JsonPatchDocument
. Configure this in ConfigureServices()
method:
services.AddControllersWithViews
.AddNewtonsoftJson();
AutoMapper.Extensions.Microsoft.DependencyInjection to map EmployeeUpdateDto to Employee. Add a mapping profile class and configure AutoMapper in ConfigureServices()
method:
services.AddAutoMapper(typeof(Startup));
and
public class MappingpProfile : Profile
{
public MappingpProfile()
{
CreateMap<CompanyUpdateDto, Company>();
CreateMap<CompanyCreationDto, Company>();
CreateMap<Employee, EmployeeDto>();
CreateMap<EmployeeCreationDto, Employee>();
CreateMap<EmployeeUpdateDto, Employee>().ReverseMap();
}
}
В приведенном выше коде мы используем CreateMap<EmployeeUpdateDto, Employee>().ReverseMap();
для наших нужд.