views:

168

answers:

5

I am creating a webservice using Windows Communication Foundation (WCF) and I currently don't know what the best way to do validation with it is.

I have two methods: CreateCustomer(Customer) and CreateCustomers(List<Customer>).

If a client passes in a list of customers, and some of the customers are invalid, should I reject the entire request? Or should I return the ones that passed validation and label the ones that were invalid?

Or, should I only allow them to call the CreateCustomer(Customer) method and make them repeatedly call it if they want to create more than one customer?

A: 

You will reduce the back-and-forth traffic if you do as much work as feasible on each call, so accepting a list and returning errors only for the problematic cases (while processing the others) seems good. The exception of course would be for work that needs to be atomic (all or nothing) but in term of application semantics that doesn't seem to be the case here.

Alex Martelli
+2  A: 

In this type of situation, I would recommend a Transaction like approach.

Basically, you would validate all, if they don't pass, throw the exception, or other validation failed events, with the customer(s) that did not pass using an identifier or the actual objects. This will allow the person on the other side of the pipeline to identify the issues.

For saving to the database, I would look into doing this in a transaction as well, partially saving 1-7 customers, but not the 8th could cause issues.

Tom Anderson
Hello Tom. Thanks for your advise.I guess the thing that was confusing me was how i would notify the client of which record caused the error, but your right, I can let them know by providing the primary identifier.One quick followup question. Say, if 8 customers were passed in and the first one fails the validation. Would you return back to the client at that time, or would you continue to validate the other records, building up any errors? Thanks, Steven
stevenrosscampbell
Personally, I would go ahead and validate them all, and then send back all of the validation errors. This will save you some traffic back and forth, especially on error prone updates. Glad I could help.
Tom Anderson
+1  A: 

Being that you are developing a web service you would probably want to reduce the number of round trips. That being said getting rid of the CreateCustomers(list) is a bad idea.

Now the tough part. I would suggest that you leave it up to the client how they want errors to be handled. You can change the signature of the CreateCustomers method to include a bool as to whether they want all or nothing. Something like this: CreateCustomers(list, allOrNothing). The return type for this operations should be a list of objects with a property for the customer and a bool as to whether or not it was successful.

Jeremy
Thanks Jeremy. I am going to look into the allOrNothing flag approach.All the best. Steven.
stevenrosscampbell
A: 

It's up to the provider to give you data that conforms to your web service's contract. If it doesn't, you're doing them a favour in telling them which data is bad (at least, compared to all of the APIs I've developed against recently).

Accepting customers that are valid and the ones that aren't could even confuse matters more as in this situation:

I make a List custs...; of size 100 and call your CreateCustomers(custs). 20 are bad, but you provide info as to why. Turns out my data entry clerk typos a lot. Problem solved, I retry CreateCustomers(custs), but I get an error back that 80 of them already existed. Did you still create the 20 that were fixed (cause, you did that last time I passed data)?

A major benefit of having all transactions being atomic is that if something doesn't work, then you know for certain that state didn't change after a failed operation.

SnOrfus
Hello SnOrfus.You bring a very valid point to the table. I've decided to go with the atomic model of all or nothing. Thanks, Steven
stevenrosscampbell
A: 

In the scenario you described it comes down to how you want to manage the errors(faultcontract) in your WCF.

Allornothing approach will require that you create a faultcontract that could simply state that there was an error in one or more of the customer requests.

If you dont go with this approach, then you will probably want to design your datacontract / faultcontract in a way to handle each possible error and differentiate between them for each error in your List. You will also want to besure to handle duplicate entries gracefully on the return trip.

David Yancey