I'm calling a SOAP web service using WCF. When the server gots error or turns into maintenance state, it replies with a HTML document. With WCF client an TargetInvocationException will be thrown because the reply is not a soap message.
I want to intercept the HTTP response and do some process (logging for exemple) when the server turns into abnormal state. I tried the IClientMessageInspector with IEndpointBehavior, when the server replies well (even Soap Fault), the method IClientMessageInspector.AfterReceiveReply fires and i can catch the message.
But when the server replies with a HTML document (where i need that method fired), that method did not fired. i just got TargetInvocationException and within that exception i can not get the original http reponse.
Does any one faced the same problem and maybe a solution for this ?
Thanks.
I limited my WCF service to allow requests up to 1 MB. This is done via binding configuration in web.config. This is working fine and client is getting 413 error code back in response. The only problem is the response body is empty. I want to include custom message in response body but I don't find a way to do it as .NET handles it automatically.
Let me know if anyone know how to add custom message in response of large requests.
We are building up a web application and we are having some issue in displaying server side validation error messages in frontend.
To give some context, we are running a single page application where frontend is implemented in react.js and backend api in asp.net. There are a number of forms in our application we ask users to fill in, and we plan to implement form validation both on client side and server side.
The work flow we are having now is to do client side validation first, and then pass the data to backend api. Backend then would first do the same validation frontend just did, to make sure that the request does not come from a malicious user who has bypassed clientside validations rules. For a request that comes from the normal channel, it should never fail this step and if it does, however, it simply means we are dealing with a hacker.
However, there are a bit more than that in server side validation. There are information which client side has no knowledge of, e.g. is the Bank Account user just typed exists in our database ? (we don't have a dedicated api to verify this, so we have to do this at the form level after user submitted the entire form to server side).
So in conclusion, there are two parts of server side validation rules: basic validation rules that is shared with frontend, and advanced validation rules that requires database access which is only available at server side.
Now the question is, how do we inform user after they fail these two type of validations?
Below are two proposals we have come about so far
Solution 1: use HTTP 400 - Bad Request to denote a business failure
we treat that 2 types of server side validation the same way and when any request fails any validation, we send back a HTTP 400 with a json object containing detailed error messages saying why it fails. A sample response would be
HTTP 400 Bad Request
{
"bsb_name" :"bsb_name has special characters",
"bsb_number":"bsb number doesn't exist",
"amount":"amount is required"
}
Now the problem is, we are not the only party who can return HTTP 400. As we are using asp.net framework plus OWIN framework, the frameworks themselves can also send back HTTP 400 under a certain circumstances , and the HTTP 400 they send is quite different from us. This create extra work for frontend to differentiate 2 types of HTTP 400 and deal with them in different ways.
A proposal was made to to re-factor our response and instead of sending back JSON object, we send back plain string --- based on the assumption that asp.net framework/owin would send back their HTTP 400 in plain string (1). So at front end we don't have differentiate them and can handle both of them in the same way. Besides, to avoid introducing magic delimiters, we only return the first error message text rather than all of them. So a sample response could be
HTTP 400 Bad Request
"Bank account name has special characters"
and we are going to treat it the same way as a HTTP 400 returned by the asp.net framework, say,
HTTP 400 Bad Request
Request header too long
So in both cases, a site user would see an error message after submitting their form saying "Bank account name has special characters" or "Request header too long"
solution 2 : Use Business Protocol rather HTTP Protocol
If the request fails the basic server side validation, which can only happen for hackers, server would throw exception immediately which would end up with a HTTP 500. Once receiving the HTTP 500, client side would simply direct user to a general error page saying something unexpected happened without any detailed information -- we try to avoid being hacking friendly.
If the request fails the advanced server side validation though, which can happen to a normal application user, server will still return a HTTP 200 - Success, but with a different status_code denoting that this is a error response. e.g.
HTTP 200 Success
{
status_code: Err_123
error_message: "bsb doesn't exist"
}
I personally want to go with solution 2 but was told that we shouldn't use HTTP 200 for a validation error. As HTTP 200 stands for OK, using HTTP 200 in the case of server side validation failure doesn't make sense.
My understanding is, HTTP Status code is designed for HTTP protocol, and should have nothing to do with your business logic. A HTTP 200 only means client has sent the request to the server, and server has successfully handled it returned the response. Whether the response means transaction has been approved, or transaction has been rejected, or, the BSB_Number you submitted doesn't exists, it simply doesn't care. And it should NOT care.
So in the case where a transaction does get rejected, or the form has some invalid input that can only be detected at server side, we still should respond HTTP 200 but assign a different status_code, which is the equivalent of HTTP 400, BUT, it's in our business protocol. So effectively, we should distinct our business protocol from http protocol, and we can't use HTTP FAILURE to stand for a BUSINESS FAILURE(2).
Above is all my thought on this, and I welcome all comments, further discussion on this topic.
Cheers,
Bo
(1): the assumption is wrong as I recently found out that IIS can return HTTP 400 under some circumstance. When that happens, it return a HTML page.
(2): An analogy could be
**IP -- TCP -- HTTP -- BUSINESS**
If TCP layer fails, IP shouldn't be concerned;
If HTTP layer fails, TCP shouldn't be concerned;
If BUSINESS layer fails, HTTP shouldn't be concerned;
Isn't 'separate of concern' a common sense in programming?? I'm a bit surprised when seeing that somebody says "it's ok to return HTTP 400 in case of business failure"
Separation of concerns ought to be first and foremost in my opinion.
Solution one, although stating the error originates in the business layer, implies that presentation is at fault. Now it's ambiguous as to where the error is actually originating.
On the other hand, solution 2 verbosely states that the HTTP transaction was successful and that the business logic responded with an error.
Ideally (in my opinion) all errors in the server side should be trapped and reported as an error in the business logic, so that the only time HTTP errors are thrown is when the user requests a bad or sensitive page.
This causes the system to fail more gracefully, and makes it more scaleable. (If you implement your API elsewhere for example, you don't need to include the HTTP error handling in it, only the display of said error)
As an aside, this might be better suited for P.SE and not SO.
My solution is similar to solution 2. I define an entity as the response for all RESTful request.
class Entity<T>{
public int code {get;set;}
public int message {get;set;}
public T content {get;set;}
}
Whether the request is succeeded or failed, the front would get an entity and check the code. If code is 200 (or others defined), continue processing the content, otherwise display the message and return.
For a request that comes from the normal channel, it should never fail this step and if it does, however, it simply means we are dealing with a hacker.
if your API its public, why not use status code 500,...This is a way to trick people trying to access your API. But, you now if this not internal server error with read status message. Or you use Status Code 202 (The request has been accepted for processing, but the processing has not been completed. The request may or may not eventually be acted upon, as it may be disallowed when processing actually takes place. there is no facility for status returns from asynchronous operations such as this.)
if you use status code 200 or 400, and every body to know if that can be injected...but, up to you, this just my suggestion like what you need opinion.
In my opinion your 400 response code is ok. You actually need to model how you should respond to validation scenarios. For example a BaseResponse.cs would look something like this.
public class BaseResponse<T> where T: object {
public T Data {get;set;}
public bool Success {get; set;}
public IList<Error> Errors {get;set;}
}
On the other hand you may define the error class as follows
public class Error {
string Type {get;set;} // "validation", "business"
string Code {get;set;} // "VAL_1234", "BIZ_4321"
string Message {get;set;} // "Value should be greater than 10"
}
Now on the Javascript side in the react application your code is not that complicated
fetch(url)
.then((response)=> {
if(response.status === 400) {
let json = response.json();
if(json) { // you have validation errors, do something with errors property in json
}else { // 400 was returned because of some other reason
}
}
});
A more involved solution in conjunction with what I have above should work. Sample here
a few days ago I start to use a SOAP service for Joomla and VirtueMart connected by a client in C#.
I tried out about a fistful functions and it works fine.
Only one function I've trouble with when I try to use it I get an error.
The developer send me a request that work for him (with my server) but I see only few differents that are not important as I think ...
Maybe somebody can help and show me impoartant differents of the requests that may be a reason for trouble?
This is the working request done with Felx (as URL as I can't insert XML:
Working Request
And this is my request that return a server fault:
Not working Request
Has somebody any idea please?
Fiddler also return an violation but I think that does not matter in this case:
Content-Length mismatch: Response Header indicated 8.958 bytes, but server send 8.959 bytes.
Also a hint how to debug may be useful.
When I send a SOAP request to my service in the IIS locally, everything works fine.
When I send a SOAP request to the same service that running on IIS on another host, everything works fine.
But when another programmer sends a SOAP request to my service, he generally gets the right response except one method in the service that returns:
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. ---> Object reference not set to an instance of an object.</faultstring>
<detail />
</soap:Fault>
I need to understand why he is receiving this error.
His SOAP request is exactly the same as SOAP Request yet mine works and his does not.
The "Object reference" error is the hardest to troubleshoot if you don't know exactly where the error is occurring. Be sure to test for null values, as the most obvious cause for this error is an object not being initialized or a variable having a null value when it's expected to contain an object or a value.
Also, be sure that you're following best practices for error handling. Try to catch the errors at the earliest possible level unless you intentionally intend to let a higher-level error handler catch the error. The fact that you're getting this error means that the error handling is not sufficient.
Finally, I'd strongly recommend including some sort of logging mechanism for your error handlers. Save the errors to the Event Log, or a database, or even email them - anything, so that you can tell exactly where the error is. Do NOT display the error back to the user.
There are several options for this. Asp.Net Health Monitoring works fine in web services as well as standard asp.net sites. There's also ELMAH, or you can write your own code to do this.
If you follow these guidelines, you won't be in a situation where you don't understand how the error is happening. You'll have the information you need to troubleshoot properly, and your apps will be more solid.
Thanks guys for all your help. I solved the problem.
The 'SoapAction' field in the soap request had the wrong URI
I recommend using a HTTP sniffer. The http sniffer will show the SOAP properties.
The "SOAPAction" property should have something like : http://tempuri.org/YourServiceMethodName