We have a C# AJAX server that handles database requests we want to return a 400/403/500 status code on an exception so that we can understand what went on at the client side. However, all we get back is "Bad Request" in the response body.
For example, if the ADO.Net driver returns this message:
Invalid length parameter passed to the LEFT or SUBSTRING function.
Cannot insert the value NULL into column '--COLUMN--', table
'--DATABASE.SCHEMA.TABLE--'; column does not allow nulls. INSERT
fails. The statement has been terminated.
Then our AJAX Server simply returns this text:
Bad Request
I have looked at the full response headers in Chrome and there is nothing even remotely resembling this error message in there. This is the code we're using to send the error back:
catch (Exception ex)
{
//Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.SC_BAD_REQUEST;
Response.Write(ex.Message);
Response.Flush();
}
In the Java/JSP equivalent to this server we are getting the correct behavior with this code:
} catch (Exception e) {
response.sendError(response.SC_BAD_REQUEST, e.getClass() + " : " + e.getMessage());
}
There's a few things that could be going wrong, but I'd be prepared to bet that you're running on IIS7 and its defaults are causing it to rewrite the error. Try the TrySkipIisCustomErrors property and the existingResponse attribute on the httpErrors configuration setting.
The server is encapsulating the error message into a bad request to prevent secure details from reaching the client. You can modify this behavior by setting the customErrors to off, e.g.
<system.web>
<customErrors mode="Off">
</customErrors>
</system.web>
Related
In my global.asax I have written code into the Application_Error event which catches all errors and shows a generic error page to the user as well as logging/emailing the error that occurred.
However, I have realised that the error page does not return the correct status code to the browser which has meant that, to a service like UptimeRobot, the site is still seen as functioning even when the page is broken.
Is it possible to derive the correct status code from an error and return it to the browser?
By default IIS intercepts the status code and sends either the debug info or a custom error page. You can deactivate this default behavior and manually set the error code through the Response object:
Context.Response.TrySkipIisCustomErrors = true;
Context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
Context.Response.ContentType = "text/plain";
Context.Response.Write("Your error message");
I have a default.aspx page that sometimes will cause an exception that gets caught in the Global.asax file. How do I send data back to my default.aspx page to change the HTML output without doing a page refresh? Is that possible?
you will have to implement a try catch and then detect the error and take steps accordingly
so suppose you know in which line you have an error.
try
{
//error prone code
}
catch
{
reponse.write("error");
response.End()
}
doing this you will catch the error and it wont be caught in the global.asax file and the "error" string would be sent back as response to the user
*NOTE - this is just an example and th estructure of the code might differ widely depending upon the type of request GET OR POST or even if thats and AJAX based request
Information of what I have and what I am trying to achieve
I am using ServiceStack and have it up and running for what I need, however I am unable to find out how to disable the Body/Content for uncaught exceptions.
I have ServiceStack handling ALL routes.
If I navigate to a route which is not mapped to ServiceStack, I get a StatusCode of 404 (perfect) and content in the Body of the response of "Handler for Request not found: ...."
If my code throws an uncaught exception, ServiceStack will kindly return a relevant StatusCode, however it also returns a ResponseStatus with ErrorCode and Message populated.
I have DebugMode turned off, this disables the StackTrace, however I want to completely mute the entire Body of the response for exceptions.
What I have tried
I have tried a Response Filter of the following:
ResponseFilters.Add((req, res, dto)) =>
{
if (dto is Exception) res.Close();
});
it unfortunately did not work.
What I want to avoid
try{
return service.GetResponse();
} catch (Exception) {
return new HttpResult(.....);
}
My Question
How do I disable the response body for all uncaught exceptions, but still return the StatusCode? I would like null returned in the body, and StatusCodes to remain in tact.
I've tried to make my question clear, but if I have been a bit vague in any way, please ask me questions.
You should be able to override the default exception handling behavior by overriding HandleException of ServiceBase.
You can inspect the default implementation here: https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceInterface/ServiceBase.cs#L228.
I have a page (generic handler) on which I want to return the status code 500 to the client to indicate that something is wrong. I do it like this:
Response.StatusCode = 500;
Response.StatusDescription = "Internal Server Error";
And at the same time I render a friendly message telling the user that something went wrong.
But instead of seing my message, I get the default IIS message saying something like this:
Server Error
500 - Internal server error.
There is a problem with the resource you are looking for, and it cannot be displayed.
And if I go in to IIS and remove the error page for 500, I get this message:
The page cannot be displayed because an internal server error has occurred.
It works as intended in IIS6, but not in IIS7. What should I do to get it working in IIS7?
You need one more line in there to bypass IIS7 taking over (based on the 500 error code you set):
Response.TrySkipIisCustomErrors = true;
Reference: HttpResponse.TrySkipIisCustomErrors
How can I get the Compiler Error Message if I have the pageUrl?
I tried using the HttpWebRequest class, but I haven't gotten the result yet.
I have collection of pages, that must execute automatically, and if the page fails, I need it to create a log.
Thank you
You can catch all application errors in application global class (global.asax) in Application_Error handler.
Other way. You can catch exceptions in custom error module as well, just register you module in <httpModules> section and implement following function there:
void context_Error(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
Exception ex = context.Server.GetLastError();
//... here goes some code
}
Thus you have to ways to catch any error. Other task is to request all pages. As I can see from your post, you've already have such solution.
string pagetext = (new System.Net.WebClient()).DownLoadString(<url>);
//Add a better control here
if(pagetext.Contains("Server Error"))
{
`enter code here`
}
You can write a program to visit the pages, if the response of the request is a HTTP error than you can investigate further.
If you do not want to write your own program to detect errors originating from HTTP requests, you can use a testing framework like selenium.
Disclaimer: I do very little with ASP.NET type stuff.
ELMAH might help you a bit. It's an error logger for ASP.NET projects.
Where are you trying to catch these exceptions? In your website, or in an external application that is crawling a site?
In an external application, using an HttpWebRequest you'd do something like this:
string urlToTry = "http://www.example.com/ServerErrorPage.htm";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToTry);
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Process your success response.
}
catch (WebException we)
{
HttpWebResponse error = (HttpWebResponse)we.Response;
// If you want to log multiple codes, prefer a switch statement.
if (error.StatusCode == HttpStatusCode.InternalServerError)
{
// This is your 500 internal server error, perform logging.
}
}
The WebException class will give you messages like:
The remote server returned an error: (500) Internal Server Error.
Once you cast them to an HttpWebResponse, you can get at the StatusCode and perform whatever logging you require.