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 & ..."). 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.
Comment #1
Posted on Mar 31, 2011 by Massive OxUnfortunately, 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:
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
Comment #2
Posted on Mar 31, 2011 by Massive OxFixed in r819.
Comment #3
Posted on Mar 31, 2011 by Massive OxReverted 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.aspx
Comment #4
Posted on May 31, 2011 by Massive OxAny 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.
Comment #5
Posted on Aug 9, 2011 by Grumpy DogAnother 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...
Comment #6
Posted on Oct 27, 2011 by Happy HorseCould 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); }
Comment #7
Posted on Oct 27, 2011 by Happy HorseI 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... :-)
Comment #8
Posted on Oct 27, 2011 by Happy HorseI'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); }
- UnvalidatedHttpContext.cs 1.71KB
Comment #9
Posted on Oct 28, 2011 by Happy HorseFor 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/0d086dacb34929b36eda877f445feb0ce1911f1b
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.
Comment #10
Posted on Sep 12, 2012 by Massive Ox(No comment was entered for this change.)
Comment #11
Posted on Sep 13, 2012 by Massive OxThis issue was closed by revision b010515d19e3.
Comment #12
Posted on Sep 14, 2012 by Massive OxThis fix only applies to ASP.NET 4.0 and later. On ASP.NET 4.0 only, Microsoft.Web.Infrastructure will be required.
Comment #13
Posted on Oct 26, 2012 by Massive DogIs there going to be a new Nuget build that will include this fix?
Comment #14
Posted on Jan 30, 2013 by Quick CatWe've run into this too, having installed via NuGet - will there be / is there a version of the NuGet package which includes this fix?
Comment #15
Posted on Aug 1, 2013 by Happy CamelAn updated NuGet package with this fix would have just saved me a couple of hours of frustration.
Comment #16
Posted on Nov 13, 2014 by Quick ElephantComment deleted
Comment #17
Posted on Nov 13, 2014 by Quick ElephantDespite 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:
In attach you can find fixed modules. Thanks.
- ElmahErrorLogModuleFix.cs 6.37KB
Comment #18
Posted on Dec 14, 2014 by Happy CatComment deleted
Comment #19
Posted on Dec 14, 2014 by Massive RabbitComment deleted
Comment #20
Posted on Dec 14, 2014 by Massive RabbitI 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.
Has any one else encounter this same concern? And, will there be an updated Nuget package?
Comment #21
Posted on Dec 14, 2014 by Massive RabbitI 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);
Status: Fixed
Labels:
Type-Defect
Priority-Medium
Component-Logic
Milestone-Release2.0