How to show a custom error page when an application error occurred without changing the url?
When application error occurs, then how to show customer a custom error page without routing to another Url?
Inside your web.config check that the configuration looks like:
<system.web>
...
<customErrors mode="On">
<error statusCode="404" redirect="~/custom404.html"/>
<customErrors
</system.web>
<customErrors mode="On" defaultRedirect="~/custom404.html">
</customErrors>
You can do this in code too. For a MVC project one can ovverride the Controller's function OnException, perform some logging and other stuff then load the contents from an Error.URL in background where the error information is formated.
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext != null && filterContext.Exception != null && !filterContext.ExceptionHandled)
{
ViewBag.Exception = filterContext.Exception;
filterContext.Result = View("~/Views/Shared/Error.cshtml");
filterContext.ExceptionHandled = true;
Log.Error(filterContext.Exception.Message +":" + filterContext.Exception.StackTrace);
}
}
In this snippet all Controllers in the project inherit from a BaseController where the function OnException is being overridden.
Try this in your Web.config file
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="/errors/error">
</customErrors>
In any error it will redirect to the /errors/error page. Please note the redirectMode attribute. With the value ResponseRewrite the url will not change.
Now, if you want to show a different page for a specific error, you can set it with the following.
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="/errors/error">
<error statusCode="404" redirect="/errors/error404" />
<error statusCode="500" redirect="/errors/error500" />
</customErrors>
Related
I'm trying to set up 500 and 404 pages for an ASP.NET 4.5.2 Web Forms project. I've got the 404 working when the non-existent page is a .ASPX page. - I have code written to serve up a custom NotFound.aspx page in response.
My problem occurs when I am using the Web.config to serve up a 404.html page for non-existent HTML pages. My 404.html page is in the root folder. If I test this with a non-existent HTML page in the root folder, 404.html renders correctly. However, if I test it with a non-existent HTML page in a non-existent sub-folder, the 404.html is served up, but the CSS/JS paths are no longer correct? It's like it's treating the CSS/JS paths as being relevant to the non-existent sub-folder I'm specifying as part of the test?
Global.asax.cs:
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex != null && ex is HttpUnhandledException)
{
Server.ClearError();
Server.Transfer("~/Error.aspx", true);
}
if (ex != null)
{
var httpException = ex as HttpException;
if (httpException.GetHttpCode() == 404)
{
Server.ClearError();
Server.Transfer("~/NotFound.aspx", true);
}
}
}
Web.config:
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" path="404.html" responseMode="File" />
</httpErrors>
Use absolute URLs for the CSS/JS paths. For example, in your 404.html (bootstrap and jquery are just examples):
<link href="/Content/bootstrap.min.css" rel="stylesheet" />
<script src="/Scripts/jquery-3.0.0.min.js"></script>
<script src="/Scripts/bootstrap.min.js"></script>
Another setup would be to set responseMode="Redirect":
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" path="/Errors/404.html" responseMode="Redirect" />
</httpErrors>
In this example, 404.html is in folder Errors and the URLs can be relative:
<link href="../Content/bootstrap.min.css" rel="stylesheet" />
<script src="../Scripts/jquery-3.0.0.min.js"></script>
<script src="../Scripts/bootstrap.min.js"></script>
and that will work because the redirect URL is no longer relative to whatever URL you've requested.
I was able to solve it as follows:
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" path="http://localhost/myproject/404.html"
responseMode="File" />
</httpErrors>
The key takeaway is that the path must be absolute for this version to work. So my next step would be to try and set the path programmatically so that in debug mode it would go to my local and in release mode go to the production URL. I don't want to mess with Web.config transform files.
If anyone has any further info, please feel free.
I've got the following error when I have : in url address:
A potentially dangerous Request.Path value was detected from the client (:)
I want when my application get an error I can redirect to /Error/NotFound action but sometimes it doesn't happen.
For example, I have below code for handle custom errors and it works properly but when I have a potentially dangerous error controller.Execute() doesn't fire.
protected void Application_Error()
{
var lastException = Server.GetLastError();
if (lastException.GetType() != typeof(HttpException))
return;
var httpException = lastException as HttpException;
var routeData = new RouteData();
routeData.Values.Add("controller", "Error");
if (httpException?.GetHttpCode() == 404 || httpException?.GetHttpCode() == 400)
routeData.Values.Add("action", "NotFound");
if (routeData.Values.Count <= 1)
return;
try
{
IController controller = new ErrorController();
controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
catch (NullReferenceException e)
{
Console.WriteLine(e.Message);
throw new NullReferenceException();
}
}
I realize that when a potentially dangerous error occurred some property of my context such as CurrentNotification, Handler, Items, Profile, Session and User is null. I don't know exactly my context is related to this problem or not.
And here is my webconfig:
<system.web>
<compilation debug="true" targetFramework="4.6.2" />
<httpRuntime targetFramework="4.6.2" maxRequestLength="314572800" enableVersionHeader="false" requestPathInvalidCharacters="<,>,%,&,:,\,?" />
</system.web>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound" />
</httpErrors>
</system.webServer>
you can handle all types of errors in your Web.Config like this :
<customErrors mode="On" defaultRedirect="~/Error/ErrorPage/404" >
<error statusCode="404" redirect="~/Error/ErrorPage/404" />
<error statusCode="403" redirect="~/Error/ErrorPage/403" />
<error statusCode="500" redirect="~/Error/ErrorPage/500" />
</customErrors>
what i added is the
defaultRedirect
to handle any type of errors
For some reason, when entering a dud URL to a file/directory/controller that does not exist, the following error is thrown:
System.Web.HttpException
The controller for path '' was not found or does not implement IController
System.Web.Mvc.IController > GetControllerInstance(System.Web.Routing.RequestContext, System.Type)
IIS then follows the regular error handling and shows the page appropriate for a 500 Internal Server Error. A 404 Not Found error handling logic should be followed. Another web application I am testing on DOES NOT throw this HttpException when it can't find a route, and returns 404 normally. So what triggeres this HttpException?
Why and how to follow a 404 route for this type of error instead of a 500? Below is the configuration of the error handling. No other code is handling errors. So why is the 500 error always shown. It's as if the default handling handles the 'can't find controller' exception as an error when in fact it's a not-found.
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace" defaultPath="/StaticErrors/Default.html" defaultResponseMode="ExecuteURL">
<clear />
<error statusCode="404" path="/mvcError/Http404" responseMode="ExecuteURL" />
<error statusCode="500" path="/mvcError/Http500" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
<system.web>
<customErrors defaultRedirect="/StaticErrors/Default.html" mode="On" redirectMode="ResponseRewrite">
<error redirect="/mvcError/Http404" statusCode="404" />
<error redirect="/mvcError/Http500" statusCode="500" />
</customErrors>
</system.web>
Failed Request Trace shows this. Basically since no route is round, the HttpException is thrown, and the 500 route handling kicks in, instead of a 404. I'm not doing anything to overide any normal default behaviour. The HandleErrorAttribute is not being added either to the MVC filters.
You should add a filter controller to override some IIS custom error.
public class mvcErrorController : Controller
{
public ActionResult Http404()
{
Response.StatusCode = 404;
Response.TrySkipIisCustomErrors = true;
return View();
}
}
You need to remove the
redirectMode="ResponseRewrite"
Option from you customErrors tag. Unfortunately, this does mean you will have a 302 before your 404, but it will fix your issue.
Alternatively, use ASPX pages for your error pages:
<customErrors defaultRedirect="/StaticErrors/Default.html" mode="On" redirectMode="ResponseRewrite">
<error redirect="/StaticErrors/Http404.aspx" statusCode="404" />
<error redirect="/StaticErrors/Http500.aspx" statusCode="500" />
</customErrors>
There is previous discussion on this issue on SO here
I have a relatively untouched MVC4 project with the following in my Web.Release.config:
<system.web>
<customErrors mode="On" defaultRedirect="~/Error">
<error redirect="~/Error/NotFound" statusCode="404" />
</customErrors>
</system.web>
It's not working though - I get normal error pages when in Release mode.
If I place that code in my Web.Config, it works as expected. I only want this applied when in Release though.
I also tried this in web.release.config:
<system.web>
<customErrors mode="On" defaultRedirect="~/Error" xdt:Transform="Replace">
<error redirect="~/Error/NotFound" statusCode="404" />
</customErrors>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</system.web>
To no avail.
Why would this be happening?
UPDATE: If I use the following in my global.asax:
void Application_Error(object sender, EventArgs e)
{
#if DEBUG
#else
Response.Redirect("/Error");
#endif
return;
}
I get the desired behavior. I feel like I should be able to use the web.config settings only though... so I'd like to leave this open.
The problem is you're not publishing. The web.release.config file is only transformed during publish as far as I know. If you're just building and running locally that file won't be used.
Also in your Application_Error you should get the status code for the error. Something like
var exception = Server.GetLastError();
var httpException = exception as HttpException;
if (httpException != null)
{
if (httpException.GetHttpCode() == 404)
RedirectToMyNotFoundPage();
}
Otherwise you will basically just handle all errors, which may or may not be what you want to do.
If you want to handle MvcErrors, and get the controller/action that the exception occured in, you should look into Filters.
Here's a good article on error filtering if that's what you're going for.
http://blogs.msdn.com/b/gduthie/archive/2011/03/17/get-to-know-action-filters-in-asp-net-mvc-3-using-handleerror.aspx
We have a 404 page. When we are in 404 page, we have search box. if we try to search from search box, it again returns to 404 page. How could we handle this?
PS: My search button is inside user control and user control is inside masterpage.
When we go to the site below;
http://www.x.com/dk
it goes to 404.
then if we make search from th,s 404 page it directs us to the link below;
http://www.x.com/dk?404%3bhttp%3a%2f%2fwww.x.com%3a80%2fdk
my web config sets
<customErrors mode="Off" defaultRedirect="Error.aspx">
<error statusCode="404" redirect="PageNotFound.aspx" />
</customErrors>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/PageNotFound.aspx" prefixLanguageFilePath="" responseMode="ExecuteURL" />
</httpErrors>
I solved this problem via javascript
<script type="text/javascript">
$("#btnSearch").attr("onclick", "Search('/Search.aspx?text=' + encodeURI($('#txtSearchInput').val())); return false;");
function Search(text) {
location.href = text;
}
</script>