Using .Net Framework CertificationValidationMode is ignored? - itfoxtec-identity-saml2

So I have two demo applications to test. One in .net 4.7 and the other in .net core 3.1.
When running the applications I'm getting different results depending the one used.
In both of them I put the CertificationValidationMode to None.
In .Net core I'm getting this error:
ITfoxtec.Identity.Saml2.Cryptography.InvalidSignatureException: Signature is invalid.
at ITfoxtec.Identity.Saml2.Saml2Request.ValidateXmlSignature(SignatureValidation documentValidationResult)
at ITfoxtec.Identity.Saml2.Saml2Request.Read(String xml, Boolean validateXmlSignature)
at ITfoxtec.Identity.Saml2.Saml2Response.Read(String xml, Boolean validateXmlSignature)
at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.Read(String xml, Boolean validateXmlSignature)
at ITfoxtec.Identity.Saml2.Saml2PostBinding.Read(HttpRequest request, Saml2Request saml2RequestResponse, String messageName, Boolean validateXmlSignature)
at ITfoxtec.Identity.Saml2.Saml2PostBinding.UnbindInternal(HttpRequest request, Saml2Request saml2RequestResponse, String messageName)
at ITfoxtec.Identity.Saml2.Saml2Binding`1.Unbind(HttpRequest request, Saml2Response saml2Response)
which is good because I modified the assertion to extend the time for testing and at that point I'm assuming that the validation was bypassed and it is failing because it does not match.
In .Net Framework, this error is coming up:
ID4037: The key needed to verify the signature could not be resolved from the following security key
identifier
'SecurityKeyIdentifier(
IsReadOnly = False,
Count = 1,
Clause[0] = System.IdentityModel.Tokens.Saml2SecurityKeyIdentifierClause
)
'. Ensure that the SecurityTokenResolver is populated with the required key.
at System.IdentityModel.EnvelopedSignatureReader.ResolveSigningCredentials()
at System.IdentityModel.EnvelopedSignatureReader.OnEndOfRootElement()
at System.IdentityModel.EnvelopedSignatureReader.Read()
at System.Xml.XmlReader.ReadEndElement()
at System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ReadAssertion(XmlReader reader)
at System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ReadToken(XmlReader reader)
at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.ReadSecurityToken(XmlNode assertionElement)
at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.Read(String xml, Boolean validateXmlSignature)
at ITfoxtec.Identity.Saml2.Saml2PostBinding.Read(HttpRequest request, Saml2Request saml2RequestResponse, String messageName, Boolean validateXmlSignature)
at ITfoxtec.Identity.Saml2.Saml2Binding`1.ReadSamlResponse(HttpRequest request, Saml2Response saml2Response)
Here I'm thinking that the validation is happening, it is not bypassed, and it is failing. Basically the Validation Mode is ignored.
Am I thinking this wrong?
Thanks

As you say the result looks correct regarding .NET core.
It looks like the .Net Framework cannot find a certificate that match the certificate used in the SAML. 2.0 AuthnResponse. Maybe the .Net Framework application is not configured with the correct certificate? I do not think it has anything to do with the Validation Mode.

Related

IDX13510: The Saml2SecurityToken cannot be validated because the Assertion specifies a OneTimeUse

We are recieving an exception when validating an assertion with a OneTimeUse Condition. We do not see a way to override or change this behavior. Any help?
Exception: Microsoft.IdentityModel.Tokens.SecurityTokenValidationException: IDX13510: The Saml2SecurityToken cannot be validated because the Assertion specifies a OneTimeUse condition.Enforcement of the OneTimeUse condition is not supported by default.To customize the enforcement of OneTimeUse condition, extend Saml2SecurityTokenHandler and override ValidateOneTimeUseCondition. at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateOneTimeUseCondition(Saml2SecurityToken securityToken, TokenValidationParameters validationParameters) at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateConditions(Saml2SecurityToken samlToken, TokenValidationParameters validationParameters) at ITfoxtec.Identity.Saml2.Tokens.Saml2ResponseSecurityTokenHandler.ValidateToken(SecurityToken token, String tokenString, Saml2Response saml2Response, Boolean detectReplayedTokens) at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.ReadClaimsIdentity(String tokenString, Boolean detectReplayedTokens) at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.Read(String xml, Boolean validateXmlSignature, Boolean detectReplayedTokens) at ITfoxtec.Identity.Saml2.Saml2PostBinding.Read(HttpRequest request, Saml2Request saml2RequestResponse, String messageName, Boolean validateXmlSignature, Boolean detectReplayedTokens) at ITfoxtec.Identity.Saml2.Saml2Binding`1.ReadSamlResponse(HttpRequest request, Saml2Response saml2Response)
We tried exploring the options classes and extending the handler but neither seem viable.
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_381479691072dae3061c8eb476d8f638726d827456" IssueInstant="2023-01-04T19:59:55.431Z" Destination="https://p-dv-vm-tee8won:443/Relativity/Identity/98E1EA02C6824DB779469702E3C3A50DF55188D3"><saml:Issuer>https://capriza.github.io/samling/samling.html</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_b4062517bccdf96dd61be6ad16374ba6aac7bccca6" IssueInstant="2023-01-04T19:59:55.383Z"><saml:Issuer>https://capriza.github.io/samling/samling.html</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#_b4062517bccdf96dd61be6ad16374ba6aac7bccca6"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>czTc3X2L2jmH8hZmbw8CnVbLGWIOCgWpQhLb6cMIRF4=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>NH/nBTI88+D7KqA26IahTsf6bpXqSdBsGf/Bk4gvtJ9NGzfEJ14Pxh9fhYgq47begLqSY61Whoek6CQs908p8Qck37BFtvxR4gsWFULGIbb7ybsEMqajBR0pVDarxcC04bgXTa2nmMs2CO0lwl6lBMAEOQaf/03W8SxLSh2ovPQ=</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICpzCCAhACCQDuFX0Db5iljDANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEQMA4GA1UECgwHU2FtbGluZzEPMA0GA1UECwwGU2FsaW5nMRQwEgYDVQQDDAtjYXByaXphLmNvbTEmMCQGCSqGSIb3DQEJARYXZW5naW5lZXJpbmdAY2Fwcml6YS5jb20wHhcNMTgwNTE1MTgxMTEwWhcNMjgwNTEyMTgxMTEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEQMA4GA1UECgwHU2FtbGluZzEPMA0GA1UECwwGU2FsaW5nMRQwEgYDVQQDDAtjYXByaXphLmNvbTEmMCQGCSqGSIb3DQEJARYXZW5naW5lZXJpbmdAY2Fwcml6YS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJEBNDJKH5nXr0hZKcSNIY1l4HeYLPBEKJLXyAnoFTdgGrvi40YyIx9lHh0LbDVWCgxJp21BmKll0CkgmeKidvGlr3FUwtETro44L+SgmjiJNbftvFxhNkgA26O2GDQuBoQwgSiagVadWXwJKkodH8tx4ojBPYK1pBO8fHf3wOnxAgMBAAEwDQYJKoZIhvcNAQELBQADgYEACIylhvh6T758hcZjAQJiV7rMRg+Omb68iJI4L9f0cyBcJENR+1LQNgUGyFDMm9Wm9o81CuIKBnfpEE2Jfcs76YVWRJy5xJ11GFKJJ5T0NEB7txbUQPoJOeNoE736lF5vYw6YKp8fJqPW0L2PLWe9qTn8hxpdnjo3k6r5gXyl8tk=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">redactedemail#relativity.com</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2023-01-04T20:09:55.383Z" Recipient="https://p-dv-vm-tee8won:443/Relativity/Identity/98E1EA02C6824DB779469702E3C3A50DF55188D3"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2023-01-04T19:59:55.383Z" NotOnOrAfter="2023-01-04T20:09:55.383Z"><saml:AudienceRestriction><saml:Audience>https://p-dv-vm-tee8won/Relativity</saml:Audience></saml:AudienceRestriction><saml:OneTimeUse></saml:OneTimeUse></saml:Conditions><saml:AuthnStatement AuthnInstant="2023-01-04T19:59:55.383Z" SessionNotOnOrAfter="2023-01-04T20:09:55.381Z" SessionIndex="_samling_4122095_80192495"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>
I have newer herd about this problem I'm afraid.
Please add a decoded SAML 2.0 authn response which the problem.
**** EDITED ****
The SAML 2.0 authn response is rejected because it contains the OneTimeUse element.
<saml:OneTimeUse>
</saml:OneTimeUse>
The OneTimeUse element is optional in SAML 2.0. But not supported by the ITfoxtec Identity SAML library because the underling Microsoft components do not support it.
You can resolve the problem by asking the IdP to remove the empty OneTimeUse element.

How to use code file that inherits `Custom.Dnn.Code12` within `Custom.Dnn.Razor12` file?

I want to write a custom view using new version of razor page in 2sxc module. My view "_MyView.cshtml" inherits Custom.Dnn.Razor12. So I've created a file "_MyView.code.cshtml" which starts with #inherits Custom.Dnn.Code12 (tried #inherits ToSic.Sxc.Dnn.RazorComponent as well but didn't help).
So when I'm trying to call something like this within "_MyView.cshtml":
#{
Code.MyMethod();
}
it gives me error:
Error: System.Web.HttpCompileException (0x80004005): d:\Projects\mywebsite.com.ua\Host\Portals\2\2sxc\MyApp_MyView.cshtml(5): error CS0103: The name 'Code' does not exist in the current context at System.Web.Compilation.AssemblyBuilder.Compile() at System.Web.Compilation.BuildProvidersCompiler.PerformBuild() at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath) at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound) at System.Web.Compilation.BuildManager.GetCompiledType(VirtualPath virtualPath) at ToSic.Sxc.Engines.RazorEngine.CreateWebPageInstance() in C:\Projects\2sxc\2sxc\Src\Dnn\ToSic.Sxc.Dnn.Razor\Engines\Razor\RazorEngine.cs:line 146 at ToSic.Sxc.Engines.RazorEngine.InitWebpage() in C:\Projects\2sxc\2sxc\Src\Dnn\ToSic.Sxc.Dnn.Razor\Engines\Razor\RazorEngine.cs:line 155 at ToSic.Sxc.Engines.RazorEngine.Init() in C:\Projects\2sxc\2sxc\Src\Dnn\ToSic.Sxc.Dnn.Razor\Engines\Razor\RazorEngine.cs:line 80 at ToSic.Sxc.Engines.EngineBase.Init(IBlock block) in C:\Projects\2sxc\2sxc\Src\Sxc\ToSic.Sxc\Engines\EngineBase.cs:line 77 at ToSic.Sxc.Blocks.BlockBuilder.GetEngine() in C:\Projects\2sxc\2sxc\Src\Sxc\ToSic.Sxc\Blocks\BlockBuilder_Render.cs:line 227 at ToSic.Sxc.Dnn.Web.DnnClientResources.NeedsPre1025Behavior() in C:\Projects\2sxc\2sxc\Src\Dnn\ToSic.Sxc.Dnn.Core\Dnn\Web\DnnClientResources.cs:line 95 at ToSic.Sxc.Dnn.View.<>c__DisplayClass13_0.<Page_Load>b__1() in C:\Projects\2sxc\2sxc\Src\Dnn\ToSic.Sxc.Dnn\View.ascx.cs:line 82 at ToSic.Sxc.Dnn.View.TryCatchAndLogToDnn(Action action, LogCall timerWrap) in C:\Projects\2sxc\2sxc\Src\Dnn\ToSic.Sxc.Dnn\View.ascx.Errors.cs:line 22 - CONTEXT: Page: 126; Module: 1724
I understand that if I keep using old classes it might work now but it might stop working later. So how do I use this one?
I tried to look through 2sxc documentation and github code, but I didn't find a single example of it.
So what am I doing wrong? How do I use it?
The Code.xxx convention was introduced around v11 because it looked like a good idea. It kind of felt like a separation of code and layout.
https://docs.2sxc.org/net-code/razor/code-behind.html
Basically it was a kind of simplification, but not major, since you could already just do something like var code = CreateInstance("razorfile.cshtml"); to get the same effect.
But as we went to v12 and supported Oqtane - which was .net Core 3.0 at that time, we realized that this will never work on Oqtane. To us it's really important to keep the API consistent across platforms because otherwise the docs get really confusing.
Since it was such a minor feature, we decided to not support it any more on newer base classes.
So if you do have shared code, just use a something.cs file and use CreateInstance("something.cs").
For a simulated code-behind which utilizez Razor features you can still create a _xyz.code.cshtml and also instantiate it with CreateInstance(...) but this would never work in Oqtane.

Is NameId required? saml2 itfoxtec-identity-saml2

I'm setting up a saml2 authorization, and is using itfoxtec libary.
But from the idp i only get one attribute value and no NameId.
In my assertionConsumerService i get a ArgumentNullException on nameId.
They say that nameId is optional, so therefore they only send the attribute value.
So can you use itfoxtec without nameid or is it requred?
Adding stacktrace
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenReadException: IDX13102: Exception thrown while reading 'NameIDType' for Saml2SecurityToken. Inner exception: 'System.ArgumentNullException: IDX10000: The parameter 'value' cannot be a 'null' or an empty object. (Parameter 'value')
at Microsoft.IdentityModel.Tokens.Saml2.Saml2NameIdentifier.set_Value(String value)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadNameIdType(XmlDictionaryReader reader)'.
---> System.ArgumentNullException: IDX10000: The parameter 'value' cannot be a 'null' or an empty object. (Parameter 'value')
at Microsoft.IdentityModel.Tokens.Saml2.Saml2NameIdentifier.set_Value(String value)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadNameIdType(XmlDictionaryReader reader)
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadNameIdType(XmlDictionaryReader reader)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadNameId(XmlDictionaryReader reader)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadNameIdentifier(XmlDictionaryReader reader, String parentElement)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadSubject(XmlDictionaryReader reader)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadAssertion(XmlReader reader)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ReadSaml2Token(XmlReader reader)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ReadSaml2Token(String token)
at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.ReadSecurityToken(String tokenString)
at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.Read(String xml, Boolean validateXmlSignature, Boolean detectReplayedTokens)
at ITfoxtec.Identity.Saml2.Saml2PostBinding.Read(HttpRequest request, Saml2Request saml2RequestResponse, String messageName, Boolean validateXmlSignature, Boolean detectReplayedTokens)
at ITfoxtec.Identity.Saml2.Saml2Binding`1.ReadSamlResponse(HttpRequest request, Saml2Response saml2Response)
at ...Controllers.AuthorizationsController.AssertionConsumerService() in ...Areas\Client\Controllers\AuthorizationsController.cs:line 95
You can use the ITfoxtec Identity SAML2 component without a NameID, but then you are not able to do logout or single logout. NameID is optional in login but not in logout and single logout.
Where are you experiencing a ArgumentNullException?
UPDATE
I have added support for issuing SAML 2.0 tokens without a NameID and testet that the component accept tokens without NameID. You should not experience an error. Are you using the latest version 2.8.2?

How to use Hangfire in ASP.NET Core with Azure database and Active Directory Password authentication

We're trying our first use of Hangfire (v1.7.19) in an ASP.NET Core WebApi application (.NET 5). Previously they've all been old school ASP.NET, and have worked without issue.
Hangfire packages used (per the Hangfire documentation) are Hangfire.Core, Hangfire.SqlServer and Hangfire.AspNetCore. We've also tried to just use the combined Hangfire package, but are having the same results.
Lifting directly from the code on that documentation page, in ConfigureServices we add
services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(connectionString), new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
}));
which, at runtime, gives
System.ArgumentException
HResult=0x80070057
Message=Keyword not supported: 'authentication'.
Source=System.Data.SqlClient
StackTrace:
at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary`2 parsetable, String connectionString, Boolean buildChain, Dictionary`2 synonyms)
at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary`2 synonyms)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous)
at System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions)
at System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key)
at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)
at System.Data.SqlClient.SqlConnection..ctor(String connectionString)
at Hangfire.SqlServer.SqlServerStorage.<.ctor>b__6_0()
at Hangfire.SqlServer.SqlServerStorage.CreateAndOpenConnection()
at Hangfire.SqlServer.SqlServerStorage.UseConnection[T](DbConnection dedicatedConnection, Func`2 func)
at Hangfire.SqlServer.SqlServerStorage.UseConnection(DbConnection dedicatedConnection, Action`1 action)
at Hangfire.SqlServer.SqlServerStorage.Initialize()
at Hangfire.SqlServer.SqlServerStorage..ctor(String nameOrConnectionString, SqlServerStorageOptions options)
at Hangfire.SqlServer.SqlServerStorage..ctor(String nameOrConnectionString)
at Hangfire.SqlServerStorageExtensions.UseSqlServerStorage(IGlobalConfiguration configuration, String nameOrConnectionString)
The value of connectionString is
Initial Catalog=XXX;Data Source=YYY;Authentication=Active Directory Password;UID=ZZZ;PWD=PPP"
This works fine with local SqlServer and LocalDb, but not with AzureDB. The connection string is exactly the one we're also using for EntityFrameworkCore 5 (in fact, the value is assigned from context.Database.GetConnectionString()).
I've read where there were issues with AzureDB and .NET Core, but those were resolved quite some time ago. Looking through the Hangfire.SqlServer package dependencies, I see where it uses System.Data.SqlClient, and current documentation for AzureDB use all refer to Microsoft.Data.SqlClient, which makes me think that the enhancements to support Active Directory Password authentication weren't made in System.Data.SqlClient but only in the newer Microsoft.Data.SqlClient package. If that's the case, I can put in a request that Hangfire replace its SqlClient package, but want to get confirmation before I do that.
Any ideas if this is indeed the case? Is there something we can do in the meantime to fix this instead?
Thanks in advance.
Hangfire IO GitHub Issue 1827
Pointers from Sergey Odinokov
As early as 1.7.8 there has been support to use an overload of UseSqlServerStorage that accepts a Func<DbConnection> instead of a connection string where you can use a connection factory to provide the newer Microsoft.Data.SqlClient.SqlConnection which supports the Authentication keyword.
Here is the related source code
You can use this like
services.AddHangfire(config => config
// other options you listed above removed for brevity
.UseSqlServerStorage(
() => new Microsoft.Data.SqlClient.SqlConnection(<connection_string>)
, new SqlServerStorageOptions() {...}
)
);

Elmah.MVC - MVC 5 ArgumentNullException: Value cannot be null. Parameter name id:

I am receiving an error when trying to render the elmah error logs and using SQL DB. "http://localhost:5525/elmah" [ArgumentNullException: Value cannot be null.
Parameter name: id]
Elmah.ErrorLogEntry..ctor(ErrorLog log, String id, Error error) in c:\builds\ELMAH-1.2-SP2\src\Elmah\ErrorLogEntry.cs:57
Elmah.SqlErrorLog.ErrorsXmlToList(XmlReader reader, IList errorEntryList) in c:\builds\ELMAH-1.2-SP2\src\Elmah\SqlErrorLog.cs:365
Elmah.SqlErrorLog.ErrorsXmlToList(String xml, IList errorEntryList) in c:\builds\ELMAH-1.2-SP2\src\Elmah\SqlErrorLog.cs:332
Elmah.SqlErrorLog.GetErrors(Int32 pageIndex, Int32 pageSize, IList errorEntryList) in c:\builds\ELMAH-1.2-SP2\src\Elmah\SqlErrorLog.cs:186
Elmah.ErrorLogPage.OnLoad(EventArgs e) in c:\builds\ELMAH-1.2-SP2\src\Elmah\ErrorLogPage.cs:76
System.Web.UI.Control.LoadRecursive() +54
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772
I have the latest Core Elmah 1.2-SP2 and the latest Elmah.MVC 2.1.2. I installed the Nuget package Elmah.MVC with default web.config settings.
When I configure web.config to log errors to the database the errors are recorded in the database but I can't render the error page. When I don't configure the database the elmah page renders just fine.
<elmah>
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="Company" />
</elmah>
Decompiling Elmah I see in the constructor where the argument is thrown.
if (id == null)
throw new ArgumentNullException("id");
if (id.Length == 0)
throw new ArgumentException((string) null, "id");
All my ErrorId's in the database are populated GUIDs.
I am stumped as to what id is not being passed to the core elmah. Has anyone ran into this before?
I downloaded the core Elmah code and stepped through to find in SqlErrorLog.cs, method ErrorsXmlToList(XmlReader reader, IList errorEntryList) there is a call to get id which was the parameter missing: string id = reader.GetAttribute("errorId"); I lower cased "errorid" and everything worked. Obviously this is not a good solution because this is core code that everyone works with so I dug deeper.
This led me to look at stored procedure ELMAH_GetErrorsXml. I found in our database we had a lower case "errorid". I updated the stored procedure to select "errorId" and changed the core Elmah back to the original code and of course everything worked.

Resources