ASP.NET 404 httpmodule - c#

Im using a CMS product called EPiServer. We need to create our own method of displaying 404's which just can't be achieved using .NET's standard customErrors. We've writen a module which we use to check for the HttpStatusCode. We do this in the EndRequest method.
If the status is 404, we query EPiServer for the appropriate 404 page, and then Transfer the request over to that page. However this doesnt return a 404, and even if I do the following the correct status isnt returned:
HttpContext.Current.Response.StatusCode = 404;
HttpContext.Current.Response.StatusDescription = "Page not Found";
HttpContext.Current.Server.TransferRequest(newPage);
Likewise, if I do a response.redirect instead of a TransferRequest then its not a proper 404 because the url has then changed...
Whats the right way of doing this?
Thanks in advance
Al

Not a direct answer to your question but could also take a look at this open source 404 handler: https://www.coderesort.com/p/epicode/wiki/404Handler
It is also available on episervers nuget feed

Which IIS version are you using? For IIS7 or 7.5 you might need something like this:
<httpErrors errorMode="Custom">
<remove statusCode="404" />
<error statusCode="404" path="/somenotfoundpage.aspx" responseMode="ExecuteURL" />
<remove statusCode="500" />
<error statusCode="500" path="/someerrorpage.aspx" responseMode="ExecuteURL" />
</httpErrors>

You should set the status code in the codebehind of the template you're using for your 404 page.
If this is a plain content page, either create a new template or add a Status Code property to the page and logic in the code behind to send the appropriate header if this is not null or empty.

Try setting the status code on the page that you transfer to - in your error page template. I'm not sure that having a separate module is necessary - you can simply handle the HttpApplication's Error event in Global.asax.cs.

Thanks for your responses.
I actually got this working by doing the following:
In the EndRequest event handler I transferred the request off to the correct EPiServer page, and included a querystring param in the call i.e.
app.Context.Server.TransferRequest(pageUrl + "&internal=true");
Then in the PostRequestHandlerExecute event I check for the querystring param, if it exists it can only be because it's a 404 so I return the correct status:
HttpContext.Current.Response.StatusCode = 404;
HttpContext.Current.Response.StatusDescription = "Page not Found";
Works like a charm.
Thanks
higgsy

Related

ASP.NET Core Capture HTTP Status Code 413 Payload Too Large / Request Entity Too Large

In Statup.cs -> Configure:
app.UseStatusCodePagesWithReExecute("/StatusCodeError/{0}");
I was trying to capture this one:
413 Payload Too Large, Previously called "Request Entity Too Large"
I just cant seem to get any middleware to fire when a 413 is triggered, guess IIS looks after it?
Just want to know the best approach to handle this as don't really want to show the user the default iis error message.
I tried adding this in to the web.config, but then this stopped other status codes working e.g. 404:
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="413" />
<error statusCode="413" path="/StatusCodeError/413" responseMode="Redirect" />
</httpErrors>
Thank you
I figured out what was happening why the status code error page was not displaying.
I added this to StatusCodeError.cshtml.cs
public void OnPost(int statusCode)
{
OnGet(statusCode);
}
All my code was in the OnGet, but because the status code 413 was triggered on a POST nothing was happening.

How to Display Status Description for a 403 error in ASP.net MVC5?

I'm attempting to create custom 403 error page that will display the status description from the error.
I'm using the following code to trigger the 403 error
from both Controllers and Action Filters
Controller Call
return new HttpStatusCodeResult(HttpStatusCode.Forbidden,
"String_Of_Why_This_Request_is_Forbiden")
Actionfilter Call
filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden,
"String_Of_Why_This_Request_is_Forbiden")
Both of these get redirected to my Custom 403 error page.
but as the request passes through my Web config and errors controller I lose both the HTTP status code and the status description.
Web.Config
<httpErrors errorMode="Custom" existingResponse="Auto">
<remove statusCode="403" subStatusCode="0" />
<error statusCode="403" subStatusCode="0" path="/Error/Forbidden" responseMode="ExecuteURL" />
</httpErrors>
ErrorControllerAction
public ViewResult Forbidden(string errorMessage)
{
Response.StatusCode = 403;
return View("Forbidden", errorMessage);
}
My assumption is that my current handling is simply generating a new request via my errors controller.
Question
How can I do this in such a way that I can pass the Original Status Description through the Errors Controller to my View?
Well you can redirect to you controller action and pass in the error message instead.
Here's a good general article for custom error page in ASP.NET MVC
https://www.c-sharpcorner.com/UploadFile/618722/custom-error-page-in-Asp-Net-mvc/

Implementing a custom error in global.asax

In my global.asax file, I have the following code:
void Application_Error(object sender, EventArgs e)
{
Exception TheError = Server.GetLastError();
if (TheError is HttpException && ((HttpException)TheError).GetHttpCode() == 404)
{
Response.Redirect("~/404.aspx");
}
else
{
Response.Redirect("~/500.aspx");
}
}
When I navigate to an non-existing page, I get the generic error page. I don't want anything pertaining to custom error in the web.config because my plan is to add code to the global.asax file to log the exceptions. Is there a way to handle custom error with just the global.asax file?
EDIT:
The answer is not obvious, but this seems to explain it: http://www.asp.net/web-forms/tutorials/deployment/deploying-web-site-projects/displaying-a-custom-error-page-cs
If you scroll down a ways, you'll find this lovely tidbit:
Note: The custom error page is only displayed when a request is made
to a resource handled by the ASP.NET engine. As we discussed in the
Core Differences Between IIS and the ASP.NET Development Server
tutorial , the web server may handle certain requests itself. By
default, the IIS web server processes requests for static content like
images and HTML files without invoking the ASP.NET engine.
Consequently, if the user requests a non-existent image file they will
get back IIS's default 404 error message rather than ASP.NET's
configured error page.
I've emphasized the first line. I tested this out in the default template, and sure enough, this URL:
http://localhost:49320/fkljflkfjelk
gets you the default IIS page, whereas simply appending a .aspx makes the Application_Error kick in. So, it sounds like you need to enable customErrors/httpErrors if you want to have all errors handled.
For IIS <= 6, add to <system.web>:
<customErrors mode="On" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="/404.aspx"/>
<error statusCode="500" redirect="/500.aspx"/>
</customErrors>
For IIS7+, add to <system.webServer>:
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="/404.aspx" responseMode="ExecuteURL"/>
<remove statusCode="500"/>
<error statusCode="500" path="/500.aspx" responseMode="ExecuteURL"/>
</httpErrors>
I'll leave the original answer in case someone finds it useful.
I believe you need to clear the existing error code from the response, otherwise IIS ignores your redirect in favor of handling the error. There's also a Boolean flag, TrySkipIisCustomErrors, you can set for newer versions of IIS (7+).
So, something like this:
void Application_Error(object sender, EventArgs e)
{
Exception TheError = Server.GetLastError();
Server.ClearError();
// Avoid IIS7 getting in the middle
Response.TrySkipIisCustomErrors = true;
if (TheError is HttpException && ((HttpException)TheError).GetHttpCode() == 404)
{
Response.Redirect("~/404.aspx");
}
else
{
Response.Redirect("~/500.aspx");
}
}
Looks like IIS is looking for a page and did not find it.
Make sure:
404.aspx is created
customErrors tag from web.config is not present.

asp.net SEO friendly 404 set redirectMode in code

I am trying to achive the below configuration through code
<customErrors defaultRedirect="GenericError.htm" mode="On"
redirectMode="ResponseRewrite">
<error statusCode="404" redirect="404.aspx"/>
</customErrors>
SEO - Handle 404 errors
if ((ex is HttpException && 404 == ((HttpException)ex).GetHttpCode()))
{
HttpContext.Current.RewritePath("~/404.aspx");
//Response.Redirect("~/404.aspx");
//Server.Transfer("~/404.aspx"); //Error executing child request for
}
Question:
How can I set redirectMode="ResponseRewrite" in programattically here?
I dont want to change the url.
Calling Response.Redirect changes the url to /404.aspx and uses 302 Http Status code.
I set Response.StatusCode=404 in page_load of 404.aspx.
Followed http://weblogs.asp.net/paxer/archive/2010/05/31/asp-net-http-404-and-seo.aspx to implement SEO friendly 404. But via code
Also HttpContext.Current.RewritePath not at all working
Server.Transfer has some errors in Application_Error, check https://stackoverflow.com/a/13344446/1909604

Custom HTTP error page

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.

Categories

Resources