Transferring business validation errors from service level to presentation level

We use the MVP pattern in our presentation layer (PL) and WCF-based service level (SL). PL calls operating contracts for SL and internally performs some business checks. If the check passes, we return the object (in the form of a contract with data) to PL.

But if the validation fails, what is the best practice we notify PL.

Entity2 Operation1(Entity1 e) { //Do some business validation and if passes pass on the updated object back to PL } 

One way is to create a common response class that is common to all transaction contracts. It will look something like this.

 public class Response { public ExceptionType exceptionType; public ExceptionInfo exceptionInfo; Collection<Entity> entityCollection; } 

ExceptionType: this is an enumeration that indicates whether businessValidation or SecurityValidation or some unknown exception has failed.

ExceptionInfo: this is an enum that reports specific details of the check / exception, e.g. errorCode, etc.

Collection. The service level may return a single object or collection of an object. We use this property to return an object or objects as required. It can also be null if the validation fails, or the method does not expect any returned object from the service level.

Is this a good approach to checking PL check errors.

For the drawback of this, I see that PL should handle all cases defined in exceptionInfo, probably use the switch case and do the necessary things.

Another way to do this is to exclude exceptions from the PL if any business verification or security verification has failed. I am not very keen on this approach because I do not want to use an exception to handle my business logic.

Any ideas for handling these scenarios?

+4
source share
1 answer

Consider:

How do you report service level messages or errors in higher layers using MVP?

I am not sure how to specifically help here. First of all, I really don’t understand your setup or I don’t know anything about WCF characteristics. Secondly, I really do not comment on exceptions for logic logic ... but I assume that you mean "business verification", as you stated elsewhere (in this case, it makes sense to me).

In my ignorance, it seems that you have the beginning of your own scheme, so perhaps you have a lot of freedom. And of course, a lot can work. So here are a few alternatives:

Communication method

You can just try your approach and see how you like it. IMO, this mix touches a little to test and work together (sometimes this may not help, especially if you start asking how to handle failures). Command-Query, on the side, is a classic throwback issue, and at that boundary you have the right to choose either as long as it works.

If you have a framework for your MVP, you can see if there is anything in it.

If you do not agree with this, you can change the PL / SL ratio to separately verify the correct operation. For instance:

 IList<Error> Validate_Operation1(Entity1 a){} Entity2 Operation1(Entity1 a){} 

Or to be crazy:

 public interface ICommand { IList<Param> Params { set; } IList<Error> Validate(); void Execute(); } 

If I firmly differentiated "Verification Errors", except for "Errors after Verification" and "Unexpected Errors", I could do the above. Getting validation issues as a result of a validation request is certainly not “exceptional”.

All that aside, you might think about getting more abstract information about what you are going to do with errors after checking. Some of them can be pushed to action, regardless of whether they are connected or not. "Datatraveler looks corrupt. Please reformat your finger pointer." Or even warnings such as "Settings not found, filled by default." If your application is very interactive, your chatty SL can use a more general mechanism to send back validation questions.

Communication Content

I don’t see your Response-class-with-error-enums-and-null objects as miles different from defining your own error or exception class, honestly. I'm not big on a “multipurpose” return like this, but there is a case for this approach: many EventArgs or asynchronous callback arguments are implemented to get error information, cancellation and results.

As for your listed flaw, I'm not sure how wide the hierarchy of errors is when you say: “PL should handle all cases defined in exceptionInfo”, so forgive me for being the worst here. The car you choose (exceptions, simple strings or the exceptionInfo enumeration) does not change the fact that if you recognize 762 different errors, you will recognize 762 different errors.

But this does not mean that your speakers should consider each of them explicitly. You have the advantage of context - you know that you will not get the "Username is empty" after the user has already logged in and checks his balance on mortgage loans. (And if you do, you should probably consider it as “Unexpected errors when checking your balance. Please try again later.” And register the call stack, right?)

Thus, your facilitator only needs to know a shorter list that is relevant to his context, and not all of them. Everything else is "Suddenly ...".

And since you are defining your own class of errors, you might consider placing your errors in string resources and binding the resource identifier to a specific error when creating the object. Then, instead of processing cases individually, many of them can be resolved with the same action: Get ID, load string, show string, done. No switch statement is required.

+2
source

All Articles