Home > database >  Fluent validation on a list of objects
Fluent validation on a list of objects

Time:09-28

Below is my request model for which I implemented fluent validation.

public class Request
{
    public List<Customer> Customers { get; set; }
}

public class Customer 
{
    public int CustNumber { get; set; } //Required field
    public string CustName { get; set; } //Required field
    public string CustAddress { get; set; } //Required field
}

Question: If Customers object has 3 items in it but CustNumber is not passed in for 1 item, is it possible to save remaining 2 items to database and an error message for the failed item with a 200 HTTP response?

My current fluent validation implementation is returning a 400 BadRequest saying "CustNumber is required".

Below is an example,

Request:

{
"Customers": [
    {
        "CustNumber": 123,
        "CustName": "Test1",
        "CustAddress": "US"
    },
    {
        "CustNumber": 456,
        "CustName": "Test2",
        "CustAddress": "US"
    },
    {
        "CustName": "Test3",
        "CustAddress": "US"
    }
  ]
}

Response:

{
"CustResult": [
    {
        "CustNumber": 123,
        "Status": "Success"
    },
    {
        "CustNumber": 456,
        "Status": "Success"
    },
    {
        "Status": "Customers[2].CustNumber is required"
    },
  ]
}

CodePudding user response:

Firstly,if you want CustNumber could be null, you set the property public int? CustNumber { get; set; }

Then,if you don't except to receive a 400 result,and keep the contrains of the table with required Attribute,you could create a DTO which doen't have required attr on property and map it to your entity

in your controller:

The cusresult you need:

var resultlist = new List<CusResult>();
for (int i= 0; i < request.Customers.Count; i  )
            {
                var num= request.Customers[i].CustNumber;
                var result = new CusResult()
                {
                    CustNumber = num,
                    Statue=num!=null?"success":String.Format("Customers[{0}].CustmorNum is required",i)
                };
                resultlist.Add(result);
            }

Update the items not null:

var updatecustomer = _mapper.Map<IEnumerable<Customer>>(request.Customers.Where(x => x.CustNumber != null));

        _context.AddRange(updatecustomer);
        _context.SaveChanges();

CodePudding user response:

It really is up to you how you want to deal with this. My personal opinion is that you should treat the HTTP request as atomic and so if the API isn't able to process the request in it's entirety you should return a 400 or 500 status.

If you control the client you may consider returning a 207 status code which indicates partial success. Although 207 was introduced for webdav specifically, there's nothing to prevent you from using it. In the response body you can specify the status of each element. The response could look like

HTTP/1.1 207 Multi-Status
Content-Type: application/json

{
  "results": [
    {
        "customer":"Test1",
        "status": 200
    },
    {
        "customer":"Test2",
        "status": 200
    },
    {
        "customer":"Test3",
        "status": 400,
        "description":"CustNumber is required"
    }
  ]
}
  • Related