I've created a simple webpage called mytestpage and am using the following code:
#using System
#using System.Drawing
#using System.IO
try
{
int d = 1/0;
<p>Error not caught</p>
}
catch(Exception notUsedForTesting)
{
<p>Error caught</p>
}
Instead of seeing "Error caught" text on mytestpage, my site redirects to a differing page as follows: Error.cshtml?aspxerrorpath=/mytestpage.
I would like to know how to avoid this re-direct, and handle the exception my self.
My current web.config file contains:
<customErrors mode="RemoteOnly">
<error statusCode="500" redirect="~/Error.cshtml"/>
</customErrors>
I have tried:
<customErrors mode="Off">
</customErrors>
as well, and I get the same redirect result.
Just tested it locally. It seems like the error you are getting is not a division by zero exception but rather a compile error
What happens is that your page will be compiled on the fly since you did not enable precompile. So when you navigate to the page it will trigger a compile but that 1/0 immediately error out. Your try catch logic did not even execute.
Try doing a throw new Exception(); instead of 1/0 and it should work as expected
However I would discourage you from doing complex logic directly inside View. You should try to move the try catch logic into ViewModel or at least controller level
Related
I know of a couple ways to catch 404 and 500 errors. For example, I can use web.config, route.config, global.asax, and a controller; however, I don't where to put the code to make it catch these errors. Let me tell you what I've done.
Route Config:
The route.config works for 404 errors, but it won't work for 500 errors (to my knowledge). Regardless, I DON'T want to use it because I've heard that it has some downsides to it. Also, it seems to be a very poor solution to this problem IMO.
web/Web Config:
I have tried every possible web config file I have: web.config (system.web and system.webServer) and Web.config (system.web and system.webServer) as well as the Web Debug File (system.web and system.webServer). ALL of these didn't catch the error (It frustrates me because no one will tell me where EXACTLY to put the code so it catches. i.e., place1 -> place2 -> place3 -> etc... Every answer gives me the code and either says Web.config or web.config - I know that but WHERE in Web.config or web.config?) I heard this way has restrictions, but they aren't relevant to me. I know it only works for IIS 7+. I think my team and I are using IIS 8, so that shouldn't be a problem for me. I prefer a method in global.asax or web.config/Web.config.
Global Asax:
I am using the two application error handler methods Application_EndRequest and Application_Error, both of which aren't working. The only error I get is a 200 error (this error is only caught by EndRequest), which isn't an error but quite the opposite. I don't know why I would be getting this when my page shows a 404 error. To my knowledge, it's because Global Asax isn't programmed to catch these errors, but web.config and/or Web.config, and as you know, I don't know how to make that work. I will accept a global.asax solution because I haven't heard anything bad about it, yet.
Controller:
I only tried one solution: protected override void HandleUnknownAction(string actionName), and the solution called for a route in route.config {*url}. Surprise, surprise, this didn't work either (as expected). I learned that this solution using the code {*url} to find 404 errors (or at least it was the solution I searched.) And as I said earlier, I don't want a route.config solution. If I am correct, protected override void HandleUnknownAction(string actionName) may work in global but not for me.
Tried Solutions:
protected override void HandleUnknownAction(string actionName)
protected void Application_EndRequest()
protected void Application_Error(object sender, EventArgs e)
protected override void OnException(ExceptionContext filterContext)
5.
<system.webServer>
<httpErrors errorMode="Custom" defaultResponseMode="File" >
<remove statusCode="404" />
<remove statusCode="500" />
<error statusCode="404"
path="404.html" />
<error statusCode="500"
path="500.html" />
</httpErrors>
</system.webServer>
6.
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath=""
path="http://yoursite.com/index.asp?syserror" responseMode="Redirect" />
</httpErrors>
7.
<customErrors mode="On">
<error statusCode="404" redirect="/Custom404.html" />
<error statusCode="500" redirect="/Custom500.html" />
</customErrors>
8.
routes.MapRoute(
"Error", // Route name
"Error/{errorCode}", // URL with parameters
new { controller = "Page", action = "Error", errorCode= UrlParameter.Optional }
);
9.
if (Context.Response.StatusCode == 404)
{
Response.Clear();
var rd = new RouteData();
rd.DataTokens["area"] = "AreaName"; // In case controller is in another area
rd.Values["controller"] = "Errors";
rd.Values["action"] = "NotFound";
IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
}
10.
Exception exception = Server.GetLastError();
// Log the exception.
ILogger logger = Container.Resolve<ILogger>();
logger.Error(exception);
Response.Clear();
HttpException httpException = exception as HttpException;
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
if (httpException == null)
{
routeData.Values.Add("action", "Index");
}
else //It's an Http Exception, Let's handle it.
{
switch (httpException.GetHttpCode())
{
case 404:
// Page not found.
routeData.Values.Add("action", "HttpError404");
break;
case 500:
// Server error.
routeData.Values.Add("action", "HttpError500");
break;
// Here you can handle Views to other error codes.
// I choose a General error template
default:
routeData.Values.Add("action", "General");
break;
}
}
Note: Firstly, I may have adjusted some of this solutions to fit my code, Secondly, I take no credit for this solutions. I found most, if not all, of the solutions on other forum pages. Thirdly, the only solution that worked is the 8th one; however, I believe it only works for 404s. Nevertheless, I don't want to use it because I believe it is a bad solution (correct me if I'm wrong.)
Conclusion:
I am NOT asking you to solve the solution for me. I simply need two thing: one, I need to be corrected if I was misinformed (through a comment or answer); and two, I need to know WHERE to put the code and the result of the code (through either a picture or an explanation.) If you put something like the following:
Here is code that worked for me
[Insert Code Here]
[Insert more description]
I will most likely copy the code, change it, try it, and inevitably get upset if/when it fails. If you could take the time to explain how 404 errors are caught and a global.asax or web/Web Config Solution, I will greatly appreciate it. I have been struggling with this problem for a while now, and I have put in a lot of time and effort into it, only to get vague solutions with little to no explanation as to why it catches 404/500 errors or where to put it, exactly.
Edit:
Here are the error methods I want to hit. I can assure you that they are routed in my route.config using routes.MapMvcAttributeRoutes();
[Route("~/page_not_found")]
public ActionResult PageNotFound()
{
Response.StatusCode = 404;
return View();
}
[Route("~/internal_server_error")]
public ActionResult InternalServerError()
{
Response.StatusCode = 500;
return View();
}
my experience was in this direction.
In terms of user experience, 500 redirects are made so that he does not see the wrong page. but redirecting 500 does not send exception parameters to the redirected page.
To log the error with 500, it is necessary to use global.asax.
For error handling, I have added the following code to Web.config:
<system.web>
<customErrors mode="On" defaultRedirect="~/Error.cshtml?">
</customErrors>
<system.web>
And in Global.asax.cs:
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
Response.Redirect("/Error.cshtml?");
}
However, when the redirect to /Error.cshtml? occurs, there is an error 'This page has a redirect loop'
I've searched through other similar questions (such as How to solve Redirect Loop). However, I have no other routes calling Error.cshtml -- so does anyone have any idea what is causing this loop and how I can work around it?
EDIT: There are multiple errors occurring, and therefore the error page redirect is involved in a redirect loop. Does anyone know of a way to only call Response.Redirect("~/Error.cshtml") once?
EDIT2: If I change the redirect url to a random url outside of the project (such as https://www.facebook.com/), the customError redirect works properly. Still looking for a way to redirect to project page without infinitely looping through the error
Try adding:
Server.ClearError();
first to clear the existing error before redirecting.
Add redirectMode="ResponseRewrite" to customErrors section.
I have the following code in my Global.asax file:
protected void Application_Error()
{
var exception = Server.GetLastError();
Response.Clear();
Server.ClearError();
//processing
Response.RedirectPermanent("url processed"));
}
At localhost this works fine, doing something like this:
I access to "www.somesite.com/uk/en-GB", and because this route isn't registered the Application_Error "catch" the error, process it and redirect to the correct route "www.somesite.com/en-GB". (As shown in the code above at Global.asax)
But at the server, I try to access to "www.somesite.com/uk/en-GB", and it don't goes to Application_Error, instead of that show me this error:
Anyone know how to solve this?
You didn't get an error. You got a 404 response code. You'll need to handle that scenario differently. The Application_Error only catches uncaught exceptions.
I'm running IIS 6 and I found that this problem was easily fixed with adding this to my Web.Config file under system.web:
<customErrors mode="Off">
</customErrors>
This will allow the code in Application_Error to execute.
In asp.net, I can define a custom error page like this:
<configuration>
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="/servererrors/404.aspx" />
</customErrors>
</system.web>
</configuration>
Now my question: If I replace, say 404.aspx with AnyHTTP.aspx,
and want to get the number of the http error to generalize the page, how do I get that error numer?
Try this setting in CustomErrors (ASP.NET 3.5 SP1):
<customErrors mode="RemoteOnly" defaultRedirect="/servererrors/AnyHTTP.aspx" RedirectMode="ResponseRewrite"/>
As a different solution, you can also do this in Global.asax:
void Application_Error(object sender, EventArgs e)
{
Server.Transfer("/servererrors/AnyHTTP.aspx");
}
and on your error page, load the last error:
Exception e = Server.GetLastError();
It is important to use Server.Transfer() in the Global.asax file; using Response.Redirect will throw a 302 error and you will lose the error that you wanted to catch.
Well you might take a look at http://www.raboof.com/projects/Elmah/ before you venture to deep into doing your own thing...
I'd recommend not using the web.config method. customErrors redirects to the error page, which makes little sense. Essentially it first says "oh yes, that'll work perfectly, you just need to go here instead", and then says "oh, we didn't find that". That's really a bug (if there isn't anything here, then why did the server tell me to go here, clearly to the user code it looks like you the server code messed up; they went to the right URI and then you directed them to the wrong one).
Use Server.Transfer() from global.asax, set a default HTTPHandler, or set IIS to execute (not redirect to) your .aspx or other file with your implementation. If you want the same handler to manage each error, then you could, for example, do a Server.Transfer() from global.asax, but include a query string parameter about the type of error (whether simply an HTTP status code, or something more detailed), or pass information in the HttpContext.
Coming from a desktop background I'm not sure exactly how to pass the exceptions I have caught to an Error page in order to avoid the standard exception screen being seen by my users.
My general question is how do I pass the exception from page X to my Error page in ASP.net?
I suggest using the customErrors section in the web.config:
<customErrors mode="RemoteOnly" defaultRedirect="/error.html">
<error statusCode="403" redirect="/accessdenied.html" />
<error statusCode="404" redirect="/pagenotfound.html" />
</customErrors>
And then using ELMAH to email and/or log the error.
The pattern I use is to log the error in a try/catch block (using log4net), then do a response.redirect to a simple error page. This assumes you don't need to show any error details.
If you need the exception details on a separate page, you might want to look at Server.GetLastError. I use that in global.asax (in the Application_Error event) to log unhandled exceptions and redirect to an error page.
We've had good luck capturing exceptions in the Global.asax Application_Error event, storing them in session, and redirecting to our error page. Alternately you could encode the error message and pass it to the error page in the querystring.
You can also get the exception from
Server.GetLastError();
Use the custom error pages in asp.net, you can find it in the customError section in the web.config
We capture the exception in the Global.asax file, store it in Session, the user is then redirected to the Error Page where we grab the exception for our Session variable and display the Message information to the user.
protected void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
this.Session[CacheProvider.ToCacheKey(CacheKeys.LastError)] = ex;
}
We do log the error message prior to displaying it the user.
I think you can use the global.asax -- Application_Exception handler to catch the exception and then store it for displaying in an error page.
But actually, your error page shouldn't contains code that might cause just another error. It should be simple "Oops! something went wrong" page.
If you want details on the error, use Windows' events viewer or ELMAH or employ some logging mechanism.