How to get rid of YSOD but keep the standard logging functionality? - asp.net

The default options of <system.web><customErrors> don't work very well in an ASP.NET MVC app if you want to return the actual HTTP status codes like 404, 500 etc. instead of 302 (because it works only with Web Forms).
No matter where and how I catch exceptions (like in Global.asax or in a global error handler) and "swallow" the exception (e. g. using Server.ClearError()), I have full control of what is rendered to the client but I loose the default logging (Web Events written to the Windows Event Log). This kind of logging works fine for me, it's very robust and I have Event Log monitoring anyway, so that's exactly what I want for logging.
Is there anything I can do to e. g. in Global.asax to simply force ASP.NET to log the current error as a Web Event and then clear the error?
A solution that requires ASP.NET 4 and IIS7.5 Integrated Mode would be fine.
One option that kind of works would be the use of <system.webServer><httpErrors>, however this works only with existingResponse="Replace", not Auto, because ASP.NET seems to automatically set TrySkipIisCustomErrors=true, and I would need this on Auto since a few controllers of my application need to return custom error pages (XML).
Thank you very much in advance!

Related

How to override page render for an error page?

We have an ASP.NET MVC application, and when it encounters an error you are not redirected to an erro rpage, instead the content of that page is replaced with the content of the error page. You go fix your code and press refresh and you're done.
We have another application that's written in WebForms and I'd like to get the same behavior out of it. Right now the current behavior is that when an error occurs you get redirected to ~/Error.aspx. Is it possible to make webforms behave this way? Perhaps override the page render event somehow?
This is just for development right? Displaying the error.aspx on production is much better both from a security and user experience perspective.
In order to turn off custom errors, you need to know how to turn them on. Yes? There are several places custom errors can be configured.
in IIS Create a Custom HTTP Error Response (IIS 7)
an error handler on the page, in global.asax, or in a class defined elsewhere (app_code folder perhaps)
in web.config Web.config customErrors mode
Web.config is probably the most common place. Start there.

IIS 7.5 Logs and ASP.Net 404 Custom Pages

I want to make a custom 404 page for my site but I want to log all the normal information into my IIS 7.5 logs like the default 404 deals with so my Statics program can tell me things like what page got the 404 error, what was the referring URL to that broken page, and more. Do I have to do anything special on my 404 page to do this or has ASP evolved enough to automatically do logging for me if I return a 404 status code?
How you handle the errors determines how the errors will show up in the logs/responses. If you simply use custom error pages, it will show up no different in the log than if you had used the OOTB pages. If, however, you are writing an ASP.NET application, and handle/bury the exception, nothing will show up in the logs.
If you are writing a .NET application, this blog post provides a pretty good overview on how to properly handle errors for SEO.
ASP.NET Custom Error pages can be implemented in many different ways. The "worst" way are those that return a 301 redirection to "NotFound.aspx" (or similar), which will, of course, return a 200 status code. Unfortunately the IIS Manager actually lets you specify this method. If you're finding your 404s and 500s aren't being logged then check out this setting first.
Error pages, regardless of their implementation, must not issue any redirection and must set the status code to 404, that way IIS's logger will log it accordingly (IIS inspects the headers of all outgoing responses and uses that to populate the log).

Webresource.axd doesn't load on my asp.net application running on my web farm

I'm working on an ASP.net web application. I'm getting errors on some of my pages where I get runtime JavaScript errors.
I've narrowed the problem down to a single ASP Menu control on the master page. I created a blank page with just the ASP Menu control. The ASP Menu control is bound to Web.sitemap. The page intermittently gives runtime errors.
However, if I refresh the page, the error may or may not appear on any given page load. Sometimes, it works; sometimes, the browser throws runtime errors when loading the page or when I mouse over the ASP Menu control.
When I catch the error in Visual Studio, the message is "microsoft jscript runtime error 'sys' is undefined". When I Google for this message, I find that it is usually associated with AJAX. However, the ONLY thing on the page is a single ASP control.
There is absolutely no Javascript on the page except for what gets generated by the .net framework.
What could be causing this problem?
UPDATE I've found out that my environment actually has load balancing with a web farm of three servers servicing the URL. When I access the application on any one of the servers individually by IP address, everything works fine.
To clarify, I understand that when a user hits the public-facing URL, it resolves to x.x.x.1. x.x.x.1 is the address for a switch which routes the request to either x.x.x.2, x.x.x.3, or x.x.x.4.
When I use the public-facing URL, I find that some of the axd file requests are intermittently rerouted to Error.aspx! WTF!?!?!?!?!?
I'm told that this is the result of a security feature that is meant to protect me from cross-site scripting and other assorted bad stuff. What can I do?
Update After taking out some error page auto-redirects, I get a more meaningful error message: ASP.NET Ajax client-side framework failed to load.
Make sure all the servers have the same asp.net version. Something that could affect it, is partially applying the recent Microsoft patch for the padding oracle vulnerability (to some servers, instead of All)
Make sure all the servers use the same machine key. When doing so either use protected sections or configure it at the machine level web.config / learn from the recent vulnerability to protect sensitive information in the web.config.

Global ASAX - get the server name

Can anybody tell me if there is a way for me to get the domain name of my site in the Application_Start event in the global.asax?
Normally I'd just get it from Context.Request.ServerVariables["SERVER_NAME"], but this is not available. I'd ideally also like to get the URL from the request that kicked off the application.
Hmm - from answers below, it would seem that being on IIS7 makes a difference here. This is new and there are now design guidelines to try and stop you from doing it:
IIS Blog
You can access the Context through the static HttpContext.Current member.
HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
HttpContext.Current.Request.Url;
Edit, Based on some of your comments I did some additional research
This error is due to a design change in the IIS7 Integrated pipeline that makes the request context unavailable in Application_Start event. When using the Classic mode (the only mode when running on previous versions of IIS), the request context used to be available, even though the Application_Start event has always been intended as a global and request-agnostic event in the application lifetime. Despite this, because ASP.NET applications were always started by the first request to the app, it used to be possible to get to the request context through the static HttpContext.Current field.
So you have two options
Change your application code to not use the request context (recommended).
Move the application to Classic mode (NOT recommended).
http://mvolo.com/iis7-integrated-mode-request-is-not-available-in-this-context-exception-in-applicationstart/
Your web-application could run under multiple different domains. Since there is no current request in the Application_Start event, you cannot know under which domain the application will be called.
You could however find out the machine-name using System.Environment.MachineName.
I'm guessing you are on IIS 7? Because the HttpContext is available there on IIS 6.0.
Can you consider filling that information later on? The first call to Application_BeginRequest for example?
In VB.NET, in Global.asax, I use the following:
Hosting.HostingEnvironment.ApplicationHost.GetSiteName
It corresponds to the application name in IIS.
UPDATE: It seems the method "GetSiteName" is not intended to be called directly and it doesn't work anymore for me in Visual Studio 2015 (or maybe it is because the framework version change I made). I fixed it by replacing it by:
System.Web.Hosting.HostingEnvironment.SiteName
Do you have access to the Request object at all? If so i think you could use
Request.Url.Authority
It will return the dns host name which is what you are looking for.
G
Have you tried: -
System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"]
Thanks,
Phil.

How do you do Error handling (especially SQL) in an ASP.NET project right

I have a another ASP.Net web project that I am working and I have approached error handling from different angles. I was just wondering if any seasoned and experienced developers out there had any recommendations.
Bonus points for discussions on a nice logging framework for ASP.net:)
I've used the ELMAH, (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable, on several projects and it works great:
http://code.google.com/p/elmah/
I've also used the built in Health Monitoring in ASP.NET 2.0:
http://msdn.microsoft.com/en-us/library/ms998306.aspx
It depends on the environment for which your application is targeted. But what I do is have a generic ErrorHandler.aspx page that I redirect to in the customErrors section of the web.config, and then any exception that I don't handle and hide causes the page to redirect to the error handler which lets the user know what happened and gives them the option to report it.
I would suggest deriving from System.Exception to make something that allows you to specify more specifics for the ErrorHandler.aspx page such as a FriendlyMessage property.
I use the Application_Error() event to grab unhandled exceptions. I write them to a log using the Application.Log() method, then I redirect them to a user-friendly error page.
The Application.Log() can be configured using the web.config file to direct the output to a file, the event log on the server, etc.
In some circumstances, I have also implemented my own logging using a generic TraceSource and custom Listener that logged the messages to a database table.

Resources