Use Email Address as Sitecore Account Username

Default sitecore username does not allow special characters like “at (@)”, “dot (.)”. So when try to create an account with email address as username, it will give this error:

user name is not valid in the selected domain

It is because there is a default validation on username with the regular expression “^\w[\w\s]*$”.

To let username be email address, just need to add the following setting in web.config file:

<!-- AccountNameValidation
Overwrite original setting to allow email address as Sitecore username
<setting name="AccountNameValidation" value="^[A-Za-z0-9._%+-]{1,64}@([A-Za-z0-9.-]+\.[A-Za-z]{2,4}){1,255}$" />

Value here is a regular expression for email. Of course there are many other ways of writing it. Or simply, just set value=”.+” to allow all characters.


Play with Sitecore Password Policy

Sitecore has some settings to enable password policy in web.config file (/configuration/system.web/membership/providers/add). It supports the following settings:

  1. minRequiredPasswordLength: Minimum number of characters included in the password
  2. minRequiredNonalphanumericCharacters: Minimum number of non alphanumeric characters (basically, the special characters) included in the password
  3. maxInvalidPasswordAttempts: Maxmun times a user can try password before being locked out

It works fine when you creating new users, change existing user’s password, and reset password. However, I did find a bug in Email Campaign Manager (ECM 2.1 for my case) module.

As we know, when someone subscribes with a newsletter, ECM will create a new user in Sitecore system and assign respect role to that account. While creating the new user, a auto-generated password will be attached. Now it seems ECM’s code never check on Sitecore’s password policy, so that the generated password is invalid, and blocks the user being created. Here is the error message I got:

System.Web.Services.Protocols.SoapException: Server was unable to process request. --->
  System.Web.Security.MembershipCreateUserException: The password supplied is invalid. Passwords must conform to the password strength requirements configured for the default provider. at
  System.Web.Security.Membership.CreateUser(String username, String password, String email) at
  Sitecore.Modules.EmailCampaign.Contact.CreateAnonymous(String localName, ManagerRoot root) at
  Sitecore.Modules.EmailCampaign.Contact.GetAnonymousFromEmail(String email, ManagerRoot root) at
  Sitecore.Modules.EmailCampaign.Core.TypeResolver.GetCorrectAnonymouseFromEmail(String email, ManagerRoot root) at
  Sitecore.Modules.EmailCampaign.Core.ClientApiLocal.GetAnonymousFromEmail(String email, String rootID) at
  Sitecore.Modules.EmailCampaign.ECMClientService.GetAnonymousFromEmail(String email, String rootID)

Sitecore has recognised it as a bug and the reference number is 433626 (although I cannot find its information on Knowledge Base now). A hot-fix is on the way, I’ll update on it when it is ready.

Besides, another common request from user is to have password expiration after a certain time.  I get inspiration from Enforce Password Expiration – Sitecore and modified accordingly. It’s a good post to read. ^_^

Updated on 19 Jun

Sitecore has provided a hot-fix for ECM’s create new user issue. It is for Sitecore 7.2 rev. 141226 with ECM 2.1 rev. 140214.
Add Sitecore.Support.433626.dll to \bin folder
Add Sitecore.Support.433626.config to \App_Config\Include folder

It is tested working for my solution. Feel free to take the files.

Error When Rendering WFFM Form in Page Editor

My project is in testing stage now. One error submitted has the behaviour like this: In Page Editor Mode, when user goes to a page with WFFM form included, it will give the yellow error page with message:

[InvalidOperationException: folder]
  Sitecore.Form.Core.Configuration.ThemesManager.GetThemeName(Item form, ID fieldID) +578
  Sitecore.Form.Core.Configuration.ThemesManager.GetThemeUrl(Item form, Boolean deviceDependant) +270
  Sitecore.Form.Core.Configuration.ThemesManager.ScriptsTags(Item form, Item contextItem) +49
  Sitecore.Form.Core.Configuration.ThemesManager.RegisterCssScript(Page page, Item form, Item contextItem) +184
  Sitecore.Form.Web.UI.Controls.SitecoreSimpleFormAscx.OnInit(EventArgs e) +233
  System.Web.UI.Control.InitRecursive(Control namingContainer) +186
  System.Web.UI.Control.AddedControl(Control control, Int32 index) +189
  Sitecore.Form.Core.Renderings.FormRender.OnInit(EventArgs e) +846
  System.Web.UI.Control.InitRecursive(Control namingContainer) +186
  System.Web.UI.Control.InitRecursive(Control namingContainer) +421
  System.Web.UI.Control.InitRecursive(Control namingContainer) +421
  System.Web.UI.Control.InitRecursive(Control namingContainer) +421
  System.Web.UI.Control.InitRecursive(Control namingContainer) +421
  System.Web.UI.Control.InitRecursive(Control namingContainer) +421
  System.Web.UI.Control.InitRecursive(Control namingContainer) +421
  System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2098

Here are some background information of this project. It’s is multi-site environment, where each site has it’s own form root. All form roots’ paths are configured in site definition. And there are security access setting for each site’s user. User can only see his own site’s form root folder.

Of course whenever an error occurs in testing environment, the first thing is to simulate it in development environment. Unfortunately, it’s not there. But I did notice one thing, the same error will not happen when access the item using super admin account. It gives a hint, the issue may related to access right.

Next thing is to check on the method – Sitecore.Form.Core.Configuration.ThemesManager.GetThemeName(Item form, ID fieldID).

private static string GetThemeName(Item form, ID fieldId)
    string str = string.Empty;
    if (Settings.UseThemeFromParent && ID.op_Equality(form.get_Parent().get_TemplateID(), IDs.FormFolderTemplateID))
        str = ((object) form.get_Parent().get_ID()).ToString();
    if (StringExtensions.IsNullOrEmpty(str))
        str = SiteUtils.GetFormsRootForSite(Context.get_Site());
    Item obj1 = form;
    if (ID.op_Inequality(form.get_TemplateID(), IDs.FormFolderTemplateID))
        obj1 = form.get_Database().GetItem(str);
    Assert.IsNotNull((object) obj1, "folder");
    if (string.IsNullOrEmpty(((BaseItem) obj1).get_Fields().get_Item(fieldId).get_Value()))
        return "Default";
    Item obj2 = form.get_Database().GetItem(((BaseItem) obj1).get_Fields().get_Item(fieldId).get_Value());
    if (obj2 == null || string.IsNullOrEmpty(obj2.get_Name()))
        return "Default";
    return obj2.get_Name();

Soon SiteUtils.GetFormsRootForSite(Context.Site) get my notice. “Context” is the most difficult / confusing / easy to get wrongly / hard to understand / … function. I should check my site definition. Yes, there’s really a difference for site definitions in development and testing environment. In testing environment, each site has its own hostName, but in development environment, they share the same one. So quickly request for new host name and apply them in development sites. Hooray, the error is now showing!

Now I can play around with it. In page’s content sublayout, I added a function to show SiteUtils.GetFormsRootForSite(Context.Site), and it gives ID {F1F7AAB6-C8CE-422F-A214-F610C109FA63}. It is /sitecore/system/Modules/Web Forms for Marketers/Website. Great, it explains why user gets error, because I didn’t give user read access of this item! After assign read access, the error is gone.

Lesson learned while resolving this issue:

  • Always keep development configuration synced with testing or even production environment, you’ll never know when the small difference will cause big trouble.
  • Give read access to Sitecore original items, even though you may not using it and keep it an empty folder.

First Blog Post O(∩_∩)O~

I’m a person not really into blogs. And yes, blog is also not popular nowadays. But I decide to start my personal blog now.

Being a web developer for almost 2 years since I graduated, I experienced and came into some really interesting situation where coding or even a simple configuration plays a magic. I guess the best way to memorise and to keep track on it, is to write it down.