I have a insert dto
public class InsertCircularStepDto
{
public Guid CircularId { get; set; }
public HashSet<CircularStepPrizeDto> Prizes { get; set; }
= new(new CircularStepPrizeDtoComparer());
}
public class CircularStepPrizeDto
{
public Guid ProductModelId { get; set; }
public Guid ProductModelUnitId { get; set; }
public int Count { get; set; }
}
With this comparer
public class CircularStepPrizeDtoComparer : IEqualityComparer<CircularStepPrizeDto>
{
public bool Equals(CircularStepPrizeDto? x, CircularStepPrizeDto? y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return x.ProductModelId.Equals(y.ProductModelId) && x.ProductModelUnitId.Equals(y.ProductModelUnitId);
}
public int GetHashCode(CircularStepPrizeDto obj)
{
return HashCode.Combine(obj.ProductModelId, obj.ProductModelUnitId);
}
}
I want to prevent duplicate records for prizes with same ProductModelId and ProductModelUnitId, when I use [HttpGet] it works correctly and if I send duplicate records for prize it gives me model state error:
[HttpGet]
public async Task<IActionResult> Create([FromQuery] InsertCircularStepDto request)
{
var result = await _circularStepFacade.InsertCircularStepService.ExecuteAsync(request);
return Ok(result);
}
But when I use [HttpPost] it doesn't works and it not prevent duplicate records of prizes with same ProductModelId and ProductModelUnitId:
// Not works
[HttpPost]
public async Task<IActionResult> Create([FromBody] InsertCircularStepDto request)
{
var result = await _circularStepFacade.InsertCircularStepService.ExecuteAsync(request);
return Ok(result);
}
Why my comparer works in [HttpGet] and it doesn't work in [HttpPost], I asked chat GPT And gives me this code and it's works in [HttpPost] but it doesn't return model state error, if I send duplicate records for prizes, it just remove duplicate records not return model state error:
public class InsertCircularStepDto
{
public Guid CircularId { get; set; }
private HashSet<CircularStepPrizeDto> _prizes = new(new CircularStepPrizeDtoComparer());
public List<CircularStepPrizeDto> Prizes
{
get => _prizes.ToList();
set => _prizes = new HashSet<CircularStepPrizeDto>(value, new CircularStepPrizeDtoComparer());
}
}
but I want to know why HashSet<CircularStepPrizeDto> not works for me in [HttpPost] ?
Looks like a code smell, the real solution is to decouple the class that implements IEqualityComparer out of the DTO.
This is how the model binding works the GET the model binding occurs through the query string, and POST is via the the body - so it deserilized as JSON data, it relates to the fact that its creates the collection first without considering the comparer.
If you still want to keep your solution without de-coupling the comperare from the DTO you can modify the model binding de-serilization or use a custom comparer logic