maoyuan121 / elmah

Automatically exported from code.google.com/p/elmah
Apache License 2.0
0 stars 0 forks source link

Request Validation errors does not get logged #217

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Post some data to a page which contains invalid data e.g. 
"<TEXT>something</TEXT>" (as default for html button content in IE6)
2. Elmah executes, but fails with the following stack trace:

System.Web.HttpRequestValidationException (0x80004005): A potentially dangerous 
Request.Form value was detected from the client (button="<TEXT>Confirm &amp; 
...").
   at System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection)
   at Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.CollectionReplacer.<>c__DisplayClass12.<ReplaceCollection>b__d(String value, String key)
   at Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyEvaluatedNameObjectEntry.ValidateObject()
   at Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyValidatingArrayList.get_Item(Int32 index)
   at System.Collections.Specialized.NameValueCollection.GetKey(Int32 index)
   at System.Collections.Specialized.NameValueCollection.Add(NameValueCollection c)
   at Elmah.Error.CopyCollection(NameValueCollection collection) in c:\dev\pub\ELMAH-1.2-BETA.dist\src\Elmah\Error.cs:line 343
   at Elmah.Error..ctor(Exception e, HttpContext context) in c:\dev\pub\ELMAH-1.2-BETA.dist\src\Elmah\Error.cs:line 132
   at Elmah.ErrorLogModule.LogException(Exception e, HttpContext context) in c:\dev\pub\ELMAH-1.2-BETA.dist\src\Elmah\ErrorLogModule.cs:line 118

What is the expected output? What do you see instead?
The exception should be logged in the normal way

What version of the product are you using? On what operating system?
Version 1.2 Beta

Please provide any additional information below.

Original issue reported on code.google.com by laings...@gmail.com on 24 Mar 2011 at 9:09

GoogleCodeExporter commented 9 years ago
Unfortunately, this is due to a breaking change[1] introduced by ASP.NET 4.0. A 
workaround right now would be to ask ASP.NET to revert back to the older 
behavior by adding the following to your configuration:

<httpRuntime requestValidationMode="2.0" />

This seems to be a valid issue for ELMAH nonetheless as the original exception 
gets lost and could be addressed by ignoring request validation errors while 
accessing those collections to capture the context.

[1] 
http://www.asp.net/learn/whitepapers/aspnet4/breaking-changes#0.1__Toc256770147

Original comment by azizatif on 31 Mar 2011 at 7:45

GoogleCodeExporter commented 9 years ago
Fixed in r819.

Original comment by azizatif on 31 Mar 2011 at 9:23

GoogleCodeExporter commented 9 years ago
Reverted in r820 and issue is re-opened. Unfortunately, the fix in r819 seemed 
promising but further testing showed that it could potentially suppress request 
input validation for the rest of the request. There seems to be no way to turn 
request input validation back on post-HttpRequestValidationException. For 
example, HttpRequest.ValidateInput[1] does not force re-validation if it is 
already in effect. It seems that to workaround this limitation, those 
collections will have to be built manually and that's too big a change to risk 
for the 1.2 release.

[1] 
http://msdn.microsoft.com/en-us/library/system.web.httprequest.validateinput.asp
x

Original comment by azizatif on 31 Mar 2011 at 11:15

GoogleCodeExporter commented 9 years ago
Any solution how to use Elmah 1.2 release to log RequestValidationException?

Web.config suggestion didn't work for me.

In MVC3
One possible way I found is to trap Application_Error event in Global.asax and 
call Elmah's Log method. However I am unable to perform redirect.

Original comment by tjs.sh...@gmail.com on 31 May 2011 at 11:42

GoogleCodeExporter commented 9 years ago
Another way to get to this issue: ASP.NET4, MVC3 application, and post 
"potentially dangerous" content to the controller. In my case, it's an XML... 
The controller action itself is decorated with ValidateInput(false), so it 
works correctly. 
But if an exception happens (other reason, not caused by the "unsafe" input), 
Error.cs throws a validation exception at the already mentioned line: _form = 
CopyCollection(request.Form);

Although adding requestValidationMode="2.0" to the web.config solves the issue, 
but not necessarily a good idea. So wrapped the CopyCollection() lines in 
try-catch blocks as a quick fix...

Original comment by AkosLuka...@gmail.com on 9 Aug 2011 at 12:07

GoogleCodeExporter commented 9 years ago
Could you use the Unvalidated request values specifically in the case of this 
exception?  There is an extension (HttpRequest.Unvalidated()) in 
System.Web.Pages which gives you the collections you need but does not perform 
validation.  The code would be something like:

if (e is HttpRequestValidationException) {
    var unvalidatedRequestValues = request.Unvalidated();
    _queryString = CopyCollection(unvalidatedRequestValues.QueryString);
    _form = CopyCollection(unvalidatedRequestValues.Form);
}

Original comment by duffett....@gmail.com on 27 Oct 2011 at 10:29

GoogleCodeExporter commented 9 years ago
I can see one big fat reason why my comment won't easily work - it would 
require you to target the .NET 4.0 framework for starters... :-)

Original comment by duffett....@gmail.com on 27 Oct 2011 at 10:35

GoogleCodeExporter commented 9 years ago
I've attached a .NET 4.0 workaround that could be used, although changes to the 
ELMAH API would be required.  It would involve referencing 
System.Web.Abstractions and being able to pass in a HttpContextBase, instead of 
only the sealed HttpContext.  You could then pass in this 
"UnvalidatedHttpContext" that provides access to the unvalidated values of the 
QueryString or Form on the Request.

Could possibly be used like this:

if (exception is HttpRequestValidationException) {
    var unvalidatedContext = new UnvalidatedHttpContext(HttpContext.Current);
    Elmah.ErrorSignal.FromContext(unvalidatedContext).Raise(exception);
}

Original comment by duffett....@gmail.com on 27 Oct 2011 at 11:22

Attachments:

GoogleCodeExporter commented 9 years ago
For anyone else that is interested in this issue I've posted a simple fix to my 
own fork that does not break the ELMAH public API here: 
https://github.com/davidduffett/Elmah/commit/0d086dacb34929b36eda877f445feb0ce19
11f1b

It simply continues to log the exception as normal, without the QueryString or 
Form data if a .NET 4.0 HttpRequestValidationException occurs when they are 
accessed.  This is satisfactory for my circumstances.

Original comment by duffett....@gmail.com on 28 Oct 2011 at 9:29

GoogleCodeExporter commented 9 years ago

Original comment by azizatif on 12 Sep 2012 at 3:47

GoogleCodeExporter commented 9 years ago
This issue was closed by revision b010515d19e3.

Original comment by azizatif on 13 Sep 2012 at 3:52

GoogleCodeExporter commented 9 years ago
This fix only applies to ASP.NET 4.0 and later. On ASP.NET 4.0 only, 
Microsoft.Web.Infrastructure will be required.

Original comment by azizatif on 14 Sep 2012 at 2:04

GoogleCodeExporter commented 9 years ago
Is there going to be a new Nuget build that will include this fix?

Original comment by j...@ukleja.com on 26 Oct 2012 at 5:43

GoogleCodeExporter commented 9 years ago
We've run into this too, having installed via NuGet - will there be / is there 
a version of the NuGet package which includes this fix?

Original comment by alexande...@gmail.com on 30 Jan 2013 at 4:28

GoogleCodeExporter commented 9 years ago
An updated NuGet package with this fix would have just saved me a couple of 
hours of frustration. 

Original comment by chris.di...@gmail.com on 1 Aug 2013 at 1:41

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Despite the fix already exists here, there is still no nuget package at 
https://www.nuget.org/packages/elmah/
So, analyzing the issue I wrote temporary solution which does not require to 
modify elmah source files. The idea is to inherit from ErrorLogModule and 
ErrorMailModule and rewrite methods where Error class is created, so that 
exception will not raise.
Then you just have to configure this modules in your web.config instead of 
elmah ones, like this:

<add name="ErrorLog" type="YourProject.SomeFolder.ElmahErrorLogModuleFix, 
YourProject" preCondition="managedHandler" />
<!--and for email module-->

In attach you can find fixed modules.
Thanks.

Original comment by maksaem...@gmail.com on 13 Nov 2014 at 8:30

Attachments:

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I implemented the fix and it works great, except now the Custom Errors Mode 
will not work.   For example, the web config settings below no longer work so 
you get routed to the default Error.cshtml view in the share folder.   
Previously, I was able to route errors based on the status code to a customer 
error handler.   Additionally, the status code is set to 0 (zero) when this 
error is logged.

   <customErrors mode="On" defaultRedirect="~/Error">
      <error statusCode="404" redirect="~/Error" />
      <error statusCode="500" redirect="~/Error" />
    </customErrors>

Has any one else encounter this same concern?  And, will there be an updated 
Nuget package?

Original comment by dden...@gmail.com on 14 Dec 2014 at 4:04

GoogleCodeExporter commented 9 years ago
I added this line "error.StatusCode = e is HttpException ? 
((HttpException)e).GetHttpCode() : 500;" and now the log shows a 500 error 
code; however, the customer error handler is still not firing.

 try
            {
                //FIX STARTS
                //Error error = new Error(e, context);
                Error error = CreateErrorSafe(e, context);
                //FIX ENDS
                ErrorLog errorLog = this.GetErrorLog(context);
                error.ApplicationName = errorLog.ApplicationName;
                error.StatusCode = e is HttpException ? ((HttpException)e).GetHttpCode() : 500;
                string id = errorLog.Log(error);
                entry = new ErrorLogEntry(errorLog, id, error);

Original comment by dden...@gmail.com on 14 Dec 2014 at 4:30