Replace Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware and use exception handling - c#

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?

Related

What response should i return in case of error from an external API?

I'm working on changes for an old user creation endpoint in a dotnet API.
In a specific endpoind for the creation of users, besides many things i'm calling Zerobounce API to validate the email of the user.
In the application that get's the response from this API it needs to act differently if the issue comes from Zerobounce, which is an email validation API.
What i've already done is:
When it fails i'll return a response with a status code 409. Which i'm not sure is the best choice but seemed fine at the beginning, but is now a problem since it can be returned in another case that doesn't involve Zerobounce .
The complete response when an error is returned is of the type:
Different solutions i thinked about:
Different ReasonPhrase for each different error with the same status code. Which means for Zerobounce errors i can tell there whats happening.
Using custom Response Headers, with this i can create for example 2 headers, one that creates a sub status code and another with the reason of failure or something else. this seems more versatile.
Start sending a body in case it fails, this might involve lots more changes, because the way the api, and website that calls the endpoint only expects a body when we have a success response, god knows where else it might break if i use this approach.
Any suggestion as the best approach is appreciatted.

.NET 5 - Correctly handling expected 404 or 400 errors in a web API

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.

Receiving different responses depending on client

I have two ASP.NET MVC web apps running on the same server. One of them is a web service that returns an error message in plain text if an exception occurs. However, right now, some clients that call the web service don't receive the error message; instead, they simply receive "Bad Request" in HTML.
The second web app (on the same server as the first) can call a URL handled by the first one and, right now, correctly receives the error message in plain text. However, I have tried calling that URL other ways, and all of them have resulted in receiving "Bad Request":
Pasting the URL into Chrome on my computer
Pasting the URL into IE on the server
Calling the URL from a web app on a different computer from the server
This error does not occur locally. When I run the 2 web apps on my computer, I receive the error message in plain text from both the second web app and from calling the local URL from Chrome.
I have narrowed down the offending line of code to the first line of the following ActionResult snippet:
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Content(errorMessage, ContentTypes.PlainText);
Removing the first line appears to fix the problem; however, that also eliminates the ability for me to use a descriptive status code. It appears to me that after the ActionResult is returned the response is being intercepted if either (a) the client is on a different computer or (b) the client is a web browser. So I guess I have a 2-part question:
Is there a reason why .NET or IIS would intercept and change a response depending on the client type or location?
Is there an easy way to view the response at any point between this code and when it's dispatched to the client?
Thanks!
Update: I changed the web app to use HttpResponseException. Now I am getting the following YSOD exception:
Processing of the HTTP request resulted in an exception. Please see
the HTTP response returned by the 'Response' property of this
exception for details.
Using MVC version 5, Visual Studio 2013. The code for the ActionResult looks like this:
MyImage image = new MyImage(parameters);
if (image.Errors.Any())
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(image.Error) });
}
return File(image.AsJpeg(), ContentTypes.Jpeg);
Anyone have an idea how to bypass this unhelpful response?
Update 2: The issue turned out to be that the error message was being suppressed because of the Web.config setting system.webServer > httpErrors > errorMode which has a default value of "DetailedLocalOnly" and seems to be invoked in some cases for a reason I don't know (although this question may start to shed some light). Once I changed it to this, it worked as I expected:
<httpErrors errorMode="Detailed" />
I understand why they suppress error messages by default on remote machines, but this was a lot harder to track down than I would have thought. Anyway, I hope this is helpful to someone in the future.
I can't think of any reason why IIS would care what client was calling a service. My guess is that the client is sending a different request to the server than what you think it is sending. You can verify this by using a program called "Fiddler".
Also, I'd recommend following a pattern that returns a HttpResponseMessage like this when sending back information from a Web API call:
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
ReasonPhrase = message,
Content = new StringContent(string.Format("{0}", exception))
};

Soap Error: "Server was unable to process request" "Object reference not set to an instance of an object"

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

Sending 500 Error Information To Yourself

Where would I need to hook in (at what event) to be able send myself every 500 error that happens on my current ASP.NET project. Something inside the global.asax? And I'd like to send myself the output that the user would see. The white/yellow/black 500 standard ASP.NET error HTML.
My users only see the errors about 10% of the time. The other 90% these are Ajax responses.
You can do this in global.asax.cs using Global Error Handling in ASP.Net using the Application_Error(...) method
If you're more interested in the end result than in the process of making it work yourself, you might like to take a look at the Elmah ("Error Logging Modules and Handlers") project - http://code.google.com/p/elmah/
It's allows you to do many things with errors - send email notifications, log them to a database, browse the error log via a web interface, and even crazy things like an RSS feed of errors or using Twitter to tweet errors.
It's quite easy to install and configure.

Categories

Resources