I'm using ServiceStack with great results so far, except that dealing with errors is seemingly tricky. If something goes wrong during serialization of a message (because I forgot to add a default constructor to the message for example) all the client gets back is a message that the server had an internal error and a status code of 500. Adding a listener to the HttpApplication.Error event in the Global.asax doesn't work as it never gets hit. Neither does Application_Error. Not only is this insufficient for end user scenarios, it makes debugging these errors very cumbersome as the only way to find out what went wrong is this ugly expression in the Quick Watch:
Encoding.Default.GetString( ((System.IO.MemoryStream)((SyncMemoryStream)((System.Net.HttpWebResponse)(((WebException)ex).Response)).ResponseStream))._buffer)
What I'd like is catch any and all errors on the server side (be it serialization by ServiceStack, or errors on my services) and add the required information to an Errors collection that all my message types have.
See ServiceStack's Validation and Error handling wiki page for more details about error handling and validation in ServiceStack.
At the moment there is no way to handle a serialization exception with Custom logic (although I will now add that on the TODO list :).
If your Response DTO has a ResponseStatus property (i.e. or inherits from IHasResponseStatus), ServiceStack should automatically serialize your exception.
To also get it to serialize your StackTrace set DebugMode to true with SetConfig() in your AppHost.Configure() onload script.
Related
I'm looking for a correct way to handle the expected errors in my web API.
For example, i have a endpoint with 2 possible responses.
200 OK, with a result object
404 Not Found, with a ApiError object, containing a small (localized) message and title.
Currently i'm throwing an custom exception at the place in my code where i know if the resource is a Ok or Not found. I got a custom middleware in place to catch these exceptions and create a nice formatted ApiError.
This works perfect, except all these (known) messages are also logged inside my log files/Application Insights. It feels weird to add a boolean to this exception where i can specify if the exception should be logged. But currently this feels like the only possible way.
Is there any advice that could make this implementation beter or maybe i should change the implementation?
Well, the issue is not .NET 5 - it is application insight.
Your middleware basically should tell AI that those specific errors ARE NOT ERRORS.
https://peter.intheazuresky.com/2020/08/21/let-application-insights-focus-on-real-problems-and-not-missing-data-404-in-your-apis/
Basically, get the ITelemetryInterface from ApplicationInsight and tell of that despite the error code, the request was a success.
Voila, problem solved. AI can not magically know that specific 404 errors are "expected" as normal operations - you will have to help it out.
It makes sense to track them on a website / web application level. It does not make sense to treat them as errors on the backend level. The response (not found) is perfectly valid, from the point of an API. Just configure AI accordingly.
Currently, our ASP.NET Core 3.1 web api's error handling sends everything to our error controller using app.UseExceptionHandling('/error'). This controller logs the error and sends the error response our clients expect. Unfortunately, our logs contain each error twice because Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware logs the error before our error controller. How can we completely remove/replace Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware such that we (a) log the error only once and (b) completely replaces the response with our content?
We decided to use app.UseExceptionHandling('/error') over app.Use<CustomMiddlewareErrorHandler>() because changing the content in middleware always produced the "response already started" error that we never see when we use the error controller. I've found tutorials that advice testing whether the response has already started, but we always want to replace it. I suppose we need to flush the response or something like that.
Can someone point me to a practical example that (a) prevents double logging and (b) allows me to completely replace the response after an error?
I'm using WEB API 2. Whenever somebody tries to insert the script into my API, I want to throw 404 or 400 error with a custom message, and not 500 error.
This is different from SO question - Getting "A potentially dangerous Request.Path value was detected from the client (&)" because I don't want to allow, but throw custom errors.
Basically, I want to just return if the script is detected, without executing any controllers, if possible.
Could you please provide some clarity on why you want to do this?
I would recommend that you look at the global.asax event Application_BeginRequest() and check the unvalidated properties in a custom method here. That will ensure you dont need to completely disable the validation and leave yourself vulnerable?
I am implementing a BufferedMediaTypeFormatter for use in a Web API project, but I can't find any details of how to handle errors when overriding ReadFromStream on BufferedMediaTypeTormatter.
I know that I should be writing errors to the IFormatterLogger.LogError method, but what should I return if the input is invalid? Should I return null? Or throw an exception? If so, which exception should be thrown?
It depends on the kind of user experience you are looking for.
If you throw an exception, Web API would short-circuit the processing of request and returns a 500 Internal Server response (with or without the exception details based on your HttpConfiguration.IncludeErrorDetailPolicy settings).
If you log errors via the IFormatterLogger.LogError (you can return null in this case), then the request processing is not short-circuited and a user would need to check for the ModelState validity to figure out if there are any errors.
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