I've come across a weird problem in my MVC4 (RC) application. (running on .NET 4.0)
I have just setup Elmah for logging exceptions / errors.
I basically installed the Elmah.MVC and elmah.sqlserver NuGet packages. (versions 2.0.0 and 1.2 respectively)
It seemed to work fine out of the box - I can go to the elmah page and view errors:
http://myserver/elmah
for example, if I create some 404 errors, they appear in this log.
What is not working is this: I have a standard MVC controller with a [HttpPost]
action. I've set it up so it will always throw an exception:
public class TestController : Controller
{
[HttpPost]
[ValidateInput(false)]
public void Testing()
{
throw new Exception("uh oh");
}
}
I then try to post data to this controller via jQuery:
$.post('/Test/Testing', {test_data: 'This is some test data'});
Ok, this works. The response returns the typical yellow screen of death, and the error is caught and logged in Elmah.
However, if I try to post something like XML/HTML the error is not logged in Elmah. I still get the same response from the server back (yellow screen of death), but nothing in Elmah.
$.post('/Test/Testing', {test_data: '<test><test1>This is some test data</test1></test>'});
Why? It doesn't make sense.
Notice I have already turned off the request validation on the action. If I didn't do that, then posting XML/HTML data would cause this exception:
A potentially dangerous Request.Form value was detected from the client
NuGet would also refuse to log that exception too - which I believe is a bug:
http://code.google.com/p/elmah/issues/detail?id=217
So what is the cause of this problem that I'm experiencing? It it a bug related to the issue I found above?
It just seems quite an unfortunate situation that I can't log exceptions just because the request contained XML/HTML.
Surely there is a way around this?
I have a work around for now, which someone suggested on http://code.google.com/p/elmah/issues/detail?id=217
You can force ASP to use the older request validation logic by adding this into the
<system.web>
section of yourWeb.config
:This will effect the app globally which is not really that great of a situation.
If anyone has something better, please let me know.
Add the following classes to your project:
and
These classes inherit from
ErrorLogModule
andErrorMailModule
and rewrite methods where theError
class is created, so that theHttpRequestValidationException
exception will not raise.Then add these to your Web.config:
to use these classes instead of the original ones. A bit of a dirty hack, but it works.
Credit goes to the poster of message #17 found here.
You can get Elmah to fire by throwing an
HttpException
instead of a normal exception.Our solution was to wrap our controller action code with a
try/catch
block, and in thecatch
block wrap the exception that is thrown by your code in anHttpException
and throw that instead. Like this:ELMAH does not catch HttpRequestValidationException by default and if a user sends an invalid request it will be missed in ELMAH's report. so it's necessary to define and use this global filter as well:
Looks like this was fixed after the current release (as of this writing) 1.2.2. I ended up explicitly logging the error in the log. This won't go through the normal processing as unhandled exceptions (email notifications, etc) but it will log it to the error log.
There was a bug in Elmah that was fixed a while back, but I don't believe any of the builds on the google code site are recent enough to include it.
As I mentioned in my comment, the issue is that if you access data through the model (MVC) or control (webforms), no problem; but if you access request.Form["inputId"] (which Elmah does when building one object), it throws an exception every time.
What I did:
After I was happy with my tests, I added the new dlls to my solution by:
filters.Add(new HandleErrorAttribute());
from FilterConfig (this allows custom errors to continue to work)In the Elmah source, the crucial piece is the use of
request.Unvalidated
in HttpRequestValidation.cs