Item has already been added. Key in dictionary: 'birthday'

May 31, 2014 at 8:25 PM
Today I upgraded from BlogEngine 2.8 to 2.9.1 and unfortunately I'm running into several issues. Primarily the admin panel was unresponsive (except just after an iisreset it seems, although I have not yet figured out how they are related).

However, I've run into another issue. I'm now getting this exception in my event log as soon as I try to access the blog front page:
Exception information: 
    Exception type: ArgumentException 
    Exception message: Item has already been added. Key in dictionary: 'birthday'  Key being added: 'birthday'
   at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
   at BlogEngine.Core.Providers.DbBlogProvider.SelectProfile(String id)
   at BlogEngine.Core.BusinessBase`2.Load(TKey id)
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at BlogEngine.Core.Providers.DbBlogProvider.FillProfiles()
   at BlogEngine.Core.AuthorProfile.get_Profiles()
   at BlogEngine.Core.AuthorProfile.GetProfile(String username)
   at post.OnInit(EventArgs e) in c:\inetpub\blog\post.aspx.cs:line 111
   at System.Web.UI.Control.InitRecursive(Control namingContainer)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
I'm using the SQL Server BlogProvider as one can see from the stack trace.

This error seemingly spontaneously started showing up after an iisreset due to unresponsiveness. I wasn't doing anything with profiles and I don't see anything strange in the be_Profiles database table. There are plenty of 'birthday' settings which seems normal to me, but there are no duplicates per ProfileID for example.

Any idea why this error is stopping my whole site from loading all of a sudden?
Jun 1, 2014 at 8:41 AM
Edited Jun 1, 2014 at 9:00 AM
Some additional information:

I've checked the backup of the 2.8 database, and the be_Profiles table contained only data for the only posting account (myself).
In the database that was failing, the table contained data for ~780 accounts, mostly created by spam bots. However, most of those accounts have been there for some time already, so it seems 2.9 is more eager to create this profile data than 2.8?

Also, I misinterpreted the data model for the be_Profiles table. ProfileID was actually the primary key for the table itself and there were indeed duplicate keys (SettingName) per UserName in some cases.

It seems that some automated process or an action on my side has triggered BlogEngine.NET to create profile data for all the accounts, and while doing so inserted some duplicate SettingNames.

After I deleted the duplicate birthday entries, the same error popped up with displayname. At this point I decided to restore the original 2.8 contents of the table, hoping to find out when this extra data is created. This seems to happen upon visiting the Users tab in the admin panel.

Hopefully the process of creating the profiles will complete normally now.
Coordinator
Jun 1, 2014 at 4:22 PM
How are you getting those 780 accounts? Self registered users? Do they get new blog created with registration?
Jun 1, 2014 at 5:38 PM
Edited Jun 1, 2014 at 5:41 PM
Self-registration yes. These users do not get their own blogs upon creation.

The registration page doesn't have the same anti-spam protection options as the comment form has, so bots tend to try to fill out the form... A couple of hours ago I removed all the garbage users, but now I have a couple of new accounts already :S

I realize 780 users is a lot for what BlogEngine.NET was supposed to do, but somehow the software managed to create some duplicate entries causing it to fail, which I would still consider a bug. The 780 users probably just made it that much more likely that the problem would occur.

Regarding the spam: some time ago I modified BE 2.8 to use an alternate spam protection (AreYouAHuman.com) which worked pretty well. Unfortunately it required changes to existing files and not merely creating an extension in 2.8. Version 2.9 seems to have changed quite a lot, but hopefully I can find some time to add it back to my blog, in which case the self-registration form would be nice to protect as well, but I seem to recall that required a very different approach.

It seems I cannot disable self-registration, at least not through the admin screen. Probably an issue similar to #12498

Anyway, for the time being I have things up and running... sort of. I can even do most admin functions if I avoid going to the Dashboard but instead go directly to the section that I need.
Coordinator
Jun 2, 2014 at 3:17 PM
Yes we need to make captures available for registration form as well as contact page etc. Email confirmation also must. Too few hours in the day :)
Jun 2, 2014 at 8:07 PM
Edited Jun 2, 2014 at 8:34 PM
I can imagine... since I'm already going crazy from the increased comment spam I'm hoping to find some time to implement the necessary changes. Protecting the registration form would be the next step for me.

I can't promise when exactly, but I could do a pull request rather than some local changes. However, I don't know the details of your plans of course...

I originally had some plans using dependency injection to make CAPTCHAs more flexible. Now that Unity is part of BlogEngine, that should be doable without adding too much infrastructure. I think it should be possible to implement CAPTCHA providers as extensions rather than having them embedded into the main codebase. However, I've not yet looked at the lastest changes in detail yet.