I have a page that's doing jQuery Ajax calls to a WebMethod in one of my ASPX pages. In some cases, my WebMethod is throwing an exception with an error message. This error message is really important for the UI, because it tells what to say to the user, so he can fix his form.
This is working fine in development environnement. But, in my production Web.Config, I need to keep customErrors set to "On", so I wont show important information. Moreover, my IIS is overriding HTTP 500 errors too.
I tried the WebServices from ASMX, and it was working perfectly. IIS wasn't overriding my HTTP 500, and customErrors was not hiding the message sent by the WebService. But migrating all my ASPX's WebMethods to ASMX files is not possible for now.
I'm looking for a guideline. How my UI can gets my WebMethod's errors, while keeping my Web.Config safe for production?
You should never show a yellow screen of death to a user.
Instead, consider implementing a Response object, contaning a boolean Success, an ErrorMessage (string) and the actual result data if needed.
You can then use a JavaScript callback and check if the call succeded. If it did not, just alert() the error message.
Related
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))
};
I have a lot of Ajax calls that connect to ASPX page instead of Web Methods (I don't have control over that).
It happens sometimes that I call an ASPX with the wrong arguments, and a HTTP 500 is throw (this is what I want). But in some cases, I really need to get the message of the error, so I can handle it in my javascript UI.
Problem is : I don't have control over the Web.Config, because my application can be use on multiple server. So the people configuring the Web.Config can do whatever they want, like forwarding a HTTP 500...
So is there a neat way to be sure that my UI will always get the error message, regardless of the Web.Config?
Well, if you end up with the same problem then me, and especially if you don't use a recent version of ASP.NET, you can always create your own way to pass errors.
This means that the server won't return an HTTP 500, but a HTTP 200 instead with a json inside that tell your client about the problem that happened. But then, $.ajax or any other libraries won't understand that, so you'll have to handle error case yourself. This is dirty, so don't o that unless you really don't have the choice.
I have a html page with ajax that has a form that is returning a value that triggers:
A potentially dangerous Request.Form value was detected from the client.
We have a wrapper class inserted between our ASPX C# code and the base classes that implements ProcessRequest (along with other calls); the primary purpose of the wrapper class being to log exceptions to our own logging mechanism.
When we get the invalid data error, we would like to display a meaningful alert but run into the PageRequestManagerParserErrorException which, while it tells a developer what the issue is, is useless to an end user.
Things which haven't worked:
Response.write (which is documented elsewhere as the cause for the parse error)
RegisterStartupScript
RegisterClientScriptBlock
I saw the post about handling file uploads which are too large but it doesn't address the issue of outputing an error message to the user.
I'm seeing some very strange behaviour when debugging my web application in VS2010 locally. The same user journey/sequence of pages happens in Production.
Debugging, I'm seeing this:
1. request for MyPage.aspx - handled by thread_1
2. (there is something on that page that IIS/ASP.Net doesn't like it seems) I'm slowly removing sections to pin-point exactly but there's
no JS, or anything fancy there just html content, user controls etc.
3. Either way a separate thread_2 to begin processing the Page_Load of my defaultdocument i.e. home.aspx is executed. There is logic in
home.aspx.cs to clear some data.
4. So when thread_1 continues processing, checks against the data above fail, resulting with the user being redirected to an error page.
Can anyone shed any light on why the second thread is created and why it starts to process my default document?
Please note:
I've checked the global methods for errors e.g. session_end,
app_error etc but nothing.
I do intermittently see a 401 error with Failed Request Tracing Logging enabled but I don't understand how that would start the
processing of my default home page?
just to sanity check, I placed a new doc test.aspx at the beginning of my defaultdocument list in the web.config and it did get called.
It seems as though, something within IIS/ASP.Net is configured to begin processing the default page on an error but this is new behaviour to me?
I've tried researching this but the only thing that seems that it could be related is thread-agility but I'm not too sure..?
It seems like there are two HTTP requests running concurrently. As each request (generally) executes on its on thread this condition would make sense.
HTTP requests by default do not share state. They operate on different data. For that reason this is not a thread-safety issue.
An exception to this rule is if you explicitly share state e.g. using static variables. You shouldn't do this for various reasons.
To debug the problem launch Fiddler and examine the HTTP request being executed. Also example HttpContext.Current.Request.RawUrl on each of the two concurrent threads.
After removing a lot of content within the faulty MyPage.aspx, I came across the guilty line of code: btnShowPost.ImageUrl = SitePath + "post.png"; (it was never accessed behind an if statement) and therefore the image <asp:Image ID="btnShowPost" runat="server" /> never set the necessary ImageUrl.
Without it, apparently this is standard browser behavior: any img, script, css, etc, with a
src= missing, will use the default path as the url. iis will usually redirect to default.aspx (or whatever is the default).
See full explanation on this link
If I were to specify a page for redirect using the ASP.NET Custom Errors feature, would my application still spit out the HTTP status code for that particular error?
For example if had a line in my web.config that had all Internal Server Errors redirect to Errors/500.aspx and then I encountered a 500 error, I would then be redirected to my custom Errors/500.aspx page. Will my application still respond with a HTTP 500 at any point in this exchange?
I'm just curious...
No, because your browser would interpret that 500 response as an error and show you it's error. Instead, it probably responds with one of the redirect status codes to send you to the defined error page.