Exception Handling in IIS7 Integrated Pipeline Mode - iis-7

I have an application hosted on IIS7 running in Integrated mode. I'm handling errors by putting the following into Web.config:
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace"
defaultResponseMode="ExecuteURL" defaultPath="/Error.aspx">
<remove statusCode="500" />
<error statusCode="500" path="/Error.aspx" responseMode="ExecuteURL" />
</httpErrors>
(Because this is Integrated mode the <customErrors> block is not used.)
I want to automatically send emails every time an exception is generated. But the problem is that within Error.aspx I can't figure out how to get a reference to the exception. I tried this:
Dim oEx As Exception = Server.GetLastError()
But it returns Nothing. I also tried HttpContext.Current.Error() and HttpContext.Current.AllErrors and those don't work either.
In a custom error page running under IIS7 Integrated mode, how do I get a reference to the handled exception?

You need to intercept the error, either in Global.asax or a custom IHttpModule implementation as follows:
public class UnhandledExceptionHandlerModule : IHttpModule {
private HttpApplication application;
public void Init(HttpApplication application)
{
this.application = httpApplication;
this.application.Error += Application_Error;
}
public void Dispose()
{
application = null;
}
protected internal void Application_Error(object sender, EventArgs e)
{
application.Transfer("~/Error.aspx");
}
}
Then, in Error.aspx.cs:
protected void Page_Load(object sender, EventArgs e) {
Response.StatusCode = 500;
// Prevent IIS from discarding our response if
// <system.webServer>/<httpErrors> is configured.
Response.TrySkipIisCustomErrors = true;
// Send error in email
SendEmail(Server.GetLastError());
// Prevent ASP.NET from redirecting if
// <system.web>/<customErrors> is configured.
Server.ClearError();
}

Related

IIS Redirecting to URL depending on locale settings from browser information

i want the IIS to redirect to a URL depending on the locale settings i get from the browser. I read about rewriting tables but i think thats not the proper way to solve that problem. The configuration of this funcionality should be only inside IIS but i am open for other suggestions.
Create a class that implements IHttpModule and then redirect based on the Request.UserLanguages value you receive:
public class MyModule : IHttpModule{
public void Init(HttpApplication application){
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
var userLanguages = context.Request.UserLanguages;
// Do something here based on the user languages
}
private void Application_EndRequest(Object source, EventArgs e)
{}
}
Then register it in your web.config
<configuration>
<system.web>
<httpModules><add name="MyModule" type="MyModule"/></httpModules>
</system.web>
</configuration>

ASP.NET WebPages use html extension

I'm trying to use ASP.NET WebPages to make sense of an existing site which uses static .html files (about 500 of them). Unfortunately, my SEO person is requiring that the site maintains its existing directory / filenames, so I need to use .html.
After finding this example, I tried adding the extension in web.config under compilation/buildProviders/ as:
<add extension=".html" type="System.Web.WebPages.Razor.RazorBuildProvider"/>
And adding an Assembly as well:
<add assembly="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
This still doesn't render the page. It is simply output as source. I also created a Global.asax at the root of the project and added this under Application_Start():
System.Web.Razor.RazorCodeLanguage.Languages.Add(
"html", new System.Web.Razor.CSharpRazorCodeLanguage());
System.Web.WebPages.WebPageHttpHandler.RegisterExtension("html");
Still had no effect. Unfortunately, I'm drawing a blank on Google.
I happened upon this question while trying to solve the same problem - although in my case, for curiosity's sake.
Here's what you need in your web.config file:
<system.web>
<compilation>
<buildProviders>
<add extension=".html"
type="System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor"/>
</buildProviders>
</compilation>
</system.web>
<system.webServer>
<handlers>
<add name="Html" verb="*" path="*.html"
type="System.Web.Webpages, WebPageHttpHandler"/>
</handlers>
</system.webServer>
This isn't enough on its own, though! We need to register the extension with WebPageHttpHandler.
Normally, you'd be able to do stuff like this in the _AppStart file - unfortunately, when the application starts (i.e when _AppStart executes), it iterates over the items in the SupportedExtensions of WebPageHttpHandler, so we can't actually register the extension in AppStart.
What I did is I made a new .dll assembly with the PreApplicationStartMethod attribute, as seen here, but you can also do it inside the Global.asax file's Application_Start method.
Finally, we also need to add "html" as an extension to the RazorCodeLanguage.Languages dictionary, so that the Razor engine can figure out how to compile the template.
Example Global.asax file:
<%# Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
System.Web.WebPages.WebPageHttpHandler.RegisterExtension("html");
var languages = System.Web.Razor.RazorCodeLanguage.Languages;
languages.Add("html", languages["cshtml"]);
}
</script>
You want to use routing. Are you using webforms or MVC?
Global.asax is a good start. Add the complete code here:
namespace Name
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
protected void Session_Start(object sender, EventArgs e)
{
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
}
protected void Application_Error(object sender, EventArgs e)
{
}
protected void Session_End(object sender, EventArgs e)
{
}
protected void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("Route1", "OldPage.html", "~/NewPage.aspx");
}
protected void Application_End(object sender, EventArgs e)
{
}
}
}
Obviously you don't want to manually add 500 routes but you can add url filters.
See: http://msdn.microsoft.com/en-us/library/cc668201.ASPX
ASP.NET routing enables you to use URLs that do not have to map to
specific files in a Web site.

What is wrong with my .net routes?

I have followed a few tutorials online and they all seem to show the same logic for .net routing using ASP.net web forms. When I execute the URL below I get a 404 error. Test.aspx is in the root folder of this application.
http://www.mydomain.com/member/abc
Here is my global.asax contents:
<%# Application Language="C#" %>
<%# Import Namespace="System.Web.Routing" %>
<script runat="server">
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute(
"TestABC",
"member/{name}",
"~/Test.aspx");
}
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
}
void Application_Error(object sender, EventArgs e)
{
}
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
}
void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
}
</script>
Is there something I need to do with my web.config file?
Any help is greatly appreciated.
I'm guessing that your routing module is not triggered when you hit the iis server.
As a test to verify that this is the cause : change your webconfig to run all managed modules upon a request.
You need to set this :
<modules runAllManagedModulesForAllRequests="true">
If that solved it you can go read this resource on why to not do that :)

How to send error info mail, if any error occurred in web application

Here the scenario is I have many .aspx pages if any page gives error, it will redirect to an error page
Web.config:
<customErrors mode="On" defaultRedirect="customErrorPage.aspx">
<error statusCode="404" redirect="Error404.aspx" />
</customErrors>
If I get 404 error it will redirect to Error404.aspx works fine.
But if their any other error (forbidden, connectionlost, service unavailable etc) then I want to redirect to customErrorPage.apsx.
I want to send an email with error information (error pagename, error statusCode) when the custom error page is displayed and later after few minutes it will auto redirect user to login.aspx.
I have tried (not working)
void Application_Error(object sender, EventArgs e)
{
ex = (HttpException)Server.GetLastError();
int errorcode = ex.GetHttpCode();
// Response.Redirect("Errorpage.aspx?id='" + errorcode + "'&msg='" + message + "'");
}
My custom error page
protected void Page_Load(object sender, EventArgs e)
{
getUrl = HttpContext.Current.Request.Url.ToString();
// string error= HttpContext.Current.Error.ToString();
// HtmlMeta meta = new HtmlMeta();
// HtmlHead head = (HtmlHead)Page.Header;
// meta.HttpEquiv = "refresh";
// meta.Content = "10; url=Login.aspx";
// head.Controls.Add(meta);
}
protected void Page_UnLoad(object sender, EventArgs e)
{
//send mail function
Email.Send("abc#asa.com", "Error Log", "custom error", true);
}
ALSO let me know if their is any other good way to this
Here how i solved :
Globasl.asax:
void Application_Error(object sender, EventArgs e)
{
Exception objErr = Server.GetLastError().GetBaseException();
string err = "<br><b>Error in: </b>" + Request.Url.ToString() +
"<br><b>Error Message: </b>" + objErr.Message.ToString() +
"<br><b>Stack Trace:</b><br>" + objErr.StackTrace.ToString();
//Email sending method
Email.Send("example#gmail.com", "Error", err, true);
}
Web.config:
<customErrors mode="Off" defaultRedirect="Customerrorpage.aspx">
<error statusCode="404" redirect="Error404.aspx" />
</customErrors>
Customerrorpage.aspx : (Auto redirect to login page in few sec)
protected void Page_Load(object sender, EventArgs e)
{
Response.AppendHeader("Refresh", "4; url=Login.aspx");
}
I suggest using ELMAH for this - it is purpose built for logging unhandled exceptions (and can be signalled to also capture other exceptions).
There are a few different nuGet packages for different configurations, including emailing the exception details.
It captures lots of data and formats it in a very readable manner.

Is it possible to execute a function at IIS for authentication before hits URLs?

Our applications are hosted at IIS as below hierarchy:
MainAppn1
---subAppn1
---subAppn2
---subAppn3
Is it possible to execute a function automatically at IIS to do authentication commonly for all sub applications whenever user hits url (for eg. http://server1/MainAppn1/subAppn1.aspx. Best answers would be greatly appreciated!.
You could implement Custom HTTP Module.
namespace AspNetWebForm
{
public class CustomHttpModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += Application_BeginRequest;
application.AuthenticateRequest += Application_AuthenticateRequest;
application.AuthorizeRequest += Application_AuthorizeRequest;
}
private void Application_BeginRequest(object sender, EventArgs e)
{
}
private void Application_AuthenticateRequest(object sender, EventArgs e)
{
}
private void Application_AuthorizeRequest(object sender, EventArgs e)
{
}
public void Dispose()
{
}
}
}
web.config
Registering the HTTP Module in IIS 7.0 Integrated Mode.
<configuration>
<system.webServer>
<modules>
<add name="CustomHttpModule" type="AspNetWebForm.CustomHttpModule"/>
</modules>
</system.webServer>
</configuration>

Resources