Reputation: 11451
I have a custom route set up:
var tradeCategoriesRoute = routes.MapRoute(
name: "TradeCategoriesIndex",
url: "TradeCategories/{*categories}",
defaults:
new
{
controller = "TradeCategories",
action = "Index"
},
namespaces: new[] {"Website.Controllers"}
);
tradeCategoriesRoute.DataTokens["UseNamespaceFallback"] = false;
tradeCategoriesRoute.RouteHandler = new CategoriesRouteHandler();
I also have a custom 404 page set up in my Global.asax:
private void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
var httpException = exception as HttpException;
DisplayErrorPage(httpException);
}
private void DisplayErrorPage(HttpException httpException)
{
Response.Clear();
var routeData = new RouteData();
if (httpException != null && httpException.GetHttpCode() == 404)
{
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "Missing");
}
else if (httpException != null && httpException.GetHttpCode() == 500)
{
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "Index");
routeData.Values.Add("status", httpException.GetHttpCode());
}
else
{
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "Index");
routeData.Values.Add("status", 500);
}
routeData.Values.Add("error", httpException);
Server.ClearError();
Response.TrySkipIisCustomErrors = true;
IController errorController = ObjectFactory.GetInstance<ErrorController>();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
Response.End();
}
It seems that my real problem is the custom route handler that I made:
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
IRouteHandler handler = new MvcRouteHandler();
var values = requestContext.RouteData.Values;
if (values["categories"] != null)
values["categoryNames"] = values["categories"].ToString().Split('/').Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
else
values["categoryNames"] = new string[0];
return handler.GetHttpHandler(requestContext);
}
It works fine and properly displays the 404 page for routes like "/doesnotexist" but doesn't work for routes like "/TradeCategories/doesnotexist". Instead I get a built in 404 page with the message "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.".
How can I get my custom 404 page working with these custom routes?
Upvotes: 1
Views: 284
Reputation: 714
Something you might want to look into is your implementation for the TradeCategories Controller's Index action. The custom route and custom handler look like they'll match basically any route (TradeCategories/*), so I'm guessing something in your action or view is returning a 404 without throwing an exception that can be caught in global.asax?
Upvotes: 1
Reputation: 6914
You need to override the Application_Error
method in you GLobal.asax
From the link:
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
// Get the exception object.
Exception exc = Server.GetLastError();
// Handle HTTP errors
if (exc.GetType() == typeof(HttpException))
{
// The Complete Error Handling Example generates
// some errors using URLs with "NoCatch" in them;
// ignore these here to simulate what would happen
// if a global.asax handler were not implemented.
if (exc.Message.Contains("NoCatch") || exc.Message.Contains("maxUrlLength"))
return;
//Redirect HTTP errors to HttpError page
Server.Transfer("HttpErrorPage.aspx");
}
// For other kinds of errors give the user some information
// but stay on the default page
Response.Write("<h2>Global Page Error</h2>\n");
Response.Write(
"<p>" + exc.Message + "</p>\n");
Response.Write("Return to the <a href='Default.aspx'>" +
"Default Page</a>\n");
// Log the exception and notify system operators
ExceptionUtility.LogException(exc, "DefaultPage");
ExceptionUtility.NotifySystemOps(exc);
// Clear the error from the server
Server.ClearError();
}
This should work. However, I would rather redirect to a different page, instead of writing to the Response
.
Something like this:
IController controller = new ErrorPageController();
controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
Response.End();
Upvotes: 0