I am trying to create a 404 error page and currently I have all of the following/tried all of the following to try and accomplish this. When the user types in :
http://name/something.aspx
It works just as its supposed to. But if the user types in:
http://name/NotAFile
with no .aspx then IIS7 takes matters into its own hands and I get the lovely error page that IIS7 comes with. The goal is that the site redirects with only a 404 status code (so not a 200, or a 302 redirect). I have tried in both the web config with:
<customErrors mode="On" defaultRedirect="~/error/Default.aspx redirectMode="ResponseRewrite">
<error statusCode="404" redirect="~/error/NotFound.aspx" />
</customErrors>
This works for the url with a .aspx file extension but not for no extension. Same with this approach in the global.asax
void Application_Error(object sender, EventArgs e)
{
var serverError = Server.GetLastError() as HttpException;
if (serverError != null)
{
if (serverError.GetHttpCode() == 404)
{
Server.ClearError();
Server.Transfer("~/error/NotFound.aspx");
}
Server.Transfer("~/error/Default.aspx");
}
}
The same results are present for this :( My final attempt was to apply this to the web config:
<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
With this I just get a plain white screen with nothing on it...
Any thoughts or comments would be greatly appreciated!! Thanks in advance!
The following codes works with both .aspx and other file types:
Global.asax
void Application_Error(object sender, EventArgs e)
{
var serverError = Server.GetLastError() as HttpException;
if (serverError != null)
{
if (serverError.GetHttpCode() == 404)
{
Server.ClearError();
Response.Redirect("~/NotFound.aspx?URL=" + Request.Url.ToString());
}
Response.Redirect("~/Default.aspx");
}
}
Web.config
<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
It seems that your application is running in classic pipeline mode. Change it to integrated and your problem will be fixed. Here is an article about pipeline modes and their differences - http://learn.iis.net/page.aspx/508/wildcard-script-mapping-and-iis-7-integrated-pipeline/
For classic asp you can use this
<system.webServer>
<httpErrors>
<clear />
<error statusCode="404" subStatusCode="-1" path="/404.html" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
<system.webServer >
<httpErrors errorMode="Custom">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="http://www.seair.co.in/Page-not-found.aspx" responseMode="Redirect" />
</httpErrors>
</system.webServer>
use the code in your config and give complete path of error page
Related
Is it possible to create a final route that catches all .. and bounces the user to a 404 view in ASP.NET MVC?
NOTE: I don't want to set this up in my IIS settings.
Found the answer myself.
Richard Dingwall has an excellent post going through various strategies. I particularly like the FilterAttribute solution. I'm not a fan of throwing exceptions around willy nilly, so i'll see if i can improve on that :)
For the global.asax, just add this code as your last route to register:
routes.MapRoute(
"404-PageNotFound",
"{*url}",
new { controller = "StaticContent", action = "PageNotFound" }
);
This question came first, but the easier answer came in a later question:
Routing for custom ASP.NET MVC 404 Error page
I got my error handling to work by creating an ErrorController that
returns the views in this article. I also had to add the "Catch All"
to the route in global.asax.
I cannot see how it will get to any of these error pages if it is not
in the Web.config..? My Web.config had to specify:
customErrors mode="On" defaultRedirect="~/Error/Unknown"
and then I also added:
error statusCode="404" redirect="~/Error/NotFound"
Hope this helps.
I love this way now because it is so simple:
<customErrors mode="On" defaultRedirect="~/Error/" redirectMode="ResponseRedirect">
<error statusCode="404" redirect="~/Error/PageNotFound/" />
</customErrors>
Also you can handle NOT FOUND error in Global.asax.cs as below
protected void Application_Error(object sender, EventArgs e)
{
Exception lastErrorInfo = Server.GetLastError();
Exception errorInfo = null;
bool isNotFound = false;
if (lastErrorInfo != null)
{
errorInfo = lastErrorInfo.GetBaseException();
var error = errorInfo as HttpException;
if (error != null)
isNotFound = error.GetHttpCode() == (int)HttpStatusCode.NotFound;
}
if (isNotFound)
{
Server.ClearError();
Response.Redirect("~/Error/NotFound");// Do what you need to render in view
}
}
Add this lines under your project root web.config File.
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Test/PageNotFound" />
<remove statusCode="500" />
<error statusCode="500" responseMode="ExecuteURL" path="/Test/PageNotFound" />
</httpErrors>
<modules>
<remove name="FormsAuthentication" />
</modules>
This might be a problem when you use
throw new HttpException(404);
When you want to catch that, I don't know any other way then editing your web config.
An alternative to creating a catch-all route is to add an Application_EndRequest method to your MvcApplication per Marco's Better-Than-Unicorns MVC 404 Answer.
Inside RouterConfig.cs add the follwing piece of code:
routes.MapRoute(
name: "Error",
url: "{id}",
defaults: new
{
controller = "Error",
action = "PageNotFound"
});
If the route cannot be resolved, then MVC framework will through 404 error..
Best approach is to use Exception Filters ... Create a custom exceptionfilter and make like this..
public class RouteNotFoundAttribute : FilterAttribute, IExceptionFilter {
public void OnException(ExceptionContext filterContext) {
filterContext.Result = new RedirectResult("~/Content/RouteNotFound.html");
}
}
I have an ASP.NET MVC application, that is deployed in the Default web site in IIS and it runs inside an application folder, e.g. http://localhost/appfolder.
I have two error pages and I tried to set them using the <httpErrors> section in web.config.
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="401" />
<remove statusCode="500" />
<error statusCode="401" responseMode="ExecuteURL" path="/appfolder/Home/NoAccess" />
<error statusCode="500" responseMode="ExecuteURL" path="/appfolder/Home/Error" />
</httpErrors>
The above setup works, but I could not make it work without using the folder name inside the paths. Based on the documentation the path attribute is relative to the site root.
If you choose the ExecuteURL response mode, the path has to be a
server relative URL (for example, /404.htm).
So, with the above in mind, the following should work, but it doesn't.
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="401" />
<remove statusCode="500" />
<error statusCode="401" responseMode="ExecuteURL" path="/Home/NoAccess" />
<error statusCode="500" responseMode="ExecuteURL" path="/Home/Error" />
</httpErrors>
Also, using ~/Home/NoAccess does not work at all, it seems that IIS simply puts ~ in the URL.
My question: Is it possible to have the above setup without having to use application folder name?
Edit: See in this snippet how my application is authorizing each request.
public class AppAutorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool authorized = false;
// Business logic to decide if authorized
return authorized;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
base.HandleUnauthorizedRequest(filterContext);
}
}
And its use in a controller is:
[HttpGet]
[AppAutorize]
public ActionResult Item(int id)
{
Models.Home.Item model = new Models.Home.Item(id);
return View("Item", model);
}
Because your web application is hosted under another website the correct site relative path for the error pages would be the one you said works. I know this isn't what you was hoping to see but the best way of handling this is to replace that httpErrors element in the Web.Release.config file like the following:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document Transform">
<system.webServer>
<httpErrors xdt:Transform="Replace">
<remove statusCode="401" />
<remove statusCode="500" />
<error statusCode="401" responseMode="ExecuteURL" path="/appfolder/Home/NoAccess" />
<error statusCode="500" responseMode="ExecuteURL" path="/appfolder/Home/Error" />
</httpErrors>
</system.webServer>
</configuration>
And keep the standard Web.config with the path excluding the appfolder path.
How I tend to do it
I tend to shy away from using the web config and instead set the HTTP errors to the following:
<httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough" />
I then have a base controller which all my controllers inherit from with methods for each error code which I want a custom page for. So in your case:
public ViewResult NoAccess()
{
Response.StatusCode = (int) HttpStatusCode.Unauthorized;
return View("NoAccess");
}
Then the usage in any of your controllers is very simple:
public ActionResult Test()
{
return NoAccess();
}
This will then render your custom view. This method of doing error pages depends on your use case but that's how I've managed to get custom error pages to work.
I have set up a custom 404 Not Found error page using the httpErrors section in my Web.config file.
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404"/>
<error statusCode="404" responseMode="ExecuteURL" path="/error/notfound"/>
</httpErrors>
When I navigate to a non-existent page, I get the following URL:
http://localhost/error/notfound?404;http://localhost/ThisPageDoesNotExist/
I don't want the query string in the URL and I don't want to 301 or 302 redirect to the notfound page either. How can I achieve this? Using URL rewriting perhaps?
If I understand you correctly, you want to handle 404 Not Found errors handled without re-writing the url and by simply returning a result view
One way to achieve this is to use the old customErrors but with redirectMode="ResponseRewrite" to ensure that the original url is not changed.
<customErrors mode="On" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="~/NotFound" />
</customErrors>
The other is to use the httpErrors method with existingResponse="Replace" Exactly the way you are currenly using it
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<clear/>
<error statusCode="404" path="/Errors/NotFound.html" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
I have tried to recreate your issue and only succeeded when I had both httpErrors and customErrors set without redirectMode="ResponseRewrite"
My Conclusion: you are probably using customErrors without ResponseRewrite which takes precedence over httpErrors handler.
If you supply your own querystring when specifying the path, then .NET will NOT tack on the aspxerrorpath.
For example:
<customErrors mode="On" defaultRedirect="errorpage.aspx?error=1" >
You could also create a HttpHandler which catches URLs with aspxerrorpath in it, and strips it. You could probably do the same with the rewrite module in IIS7 as well.
Or, in the global.asax, catch the 404 error and redirect to the file not found page. Example:
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404)
{
Response.Redirect("~/filenotfound.aspx");
}
else
{
// your global error handling here!
}
}
Hello I am trying to do a redirect if the response is a 404 but it is not working as expected, can you experts see the issue?. It still goes to the generic 404
in my Global.asax
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (Response.Status == "404 Not Found")
{
string notFound = "~/custom_notfound.aspx";
Response.Redirect(notFound);
}
}
UPDATE
Tried so far
(Response.Status == "404 Not Found")
(Response.Status == "404")
(Response.StatusCode == 404)
You can also use the web.config customerrors section - as shown here
e.g. In the system.web section,
<customErrors mode="On" defaultRedirect="/custom_error.aspx">
<error statusCode="404" redirect="/custom_notfound.aspx" />
</customErrors>
I don't think BeginRequest could know about 404 errors. Try implementing Application_Error instead. Check to see if Server.GetLastError() is an HttpException, and if so, check the status.
You could add to your web.config to do this redirection, you don't need to use Application_BeginRequest to handle this.
See this ServerFault question.
If you can't use the web.config then I would set your startup page to one that doesn't exist, put a breakpoint in your BeginRequest, debug the app and look at the request to see how to determine it is a 404. That would be much easier to determine the optimal solution.
Looking into this some more, there is a HttpStatusCode that is used in the HttpWebResponse class. So it may make sense to use a different override of the Application to get the default response, and then check it's status against the Enum.
You can also use the web.config
<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>
I am trying to create a custom error handler in iis 7.
web.config httpErrors section:
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/path/to/handlerwebservice" responseMode="ExecuteURL" />
</httpErrors>
web.config httpHandler to handle error:
<add path="*/path/to/handlerwebservice" verb="GET,HEAD" type="WebServices.Image404Handler, WebServices" validate="false" />
Image404Handler c# code:
public void ProcessRequest(HttpContext context)
{
string requestpath;
if (context.Request.QueryString.AllKeys.Contains("aspxerrorpath"))
{
requestpath = context.Request.QueryString["aspxerrorpath"];
}
else
{
requestpath = context.Request.Path;
}
// more code not really relevant here
}
I can't figure out how to get the path of the request that caused the 404 error to trigger. In IIS 6, that Visual Studio 2008 uses this path is added to aspxerrorpath in the querystring.
I can't get remote debugging to work so I am asking here if someone knows what to do.
I found an answer myself.
Use HttpСontext.Request.RawUrl instead of HttpСontext.Request.Path