4

I have a method below which is supposed to be called from an unauthenticated Sites page (via https). It is intended to take some personal details and create a Person Account with them and then activate that record for use on the customer portal.

However when I run this method I find that the return value of the Site.createPersonAccountPortalUser method is null and the person account is not created.

I have been trying to follow the instructions from the Site Class documentation without success.

I have set up a force.com site, associated it to a customer portal, enabled the profile and defined a default user profile and licence to be high-volume portal user.

public static String createPersonAccountPortalUser(String FirstName, String LastName, String Email, String Phone, Map<String, String> mResponseMap){
    ID userId;
    User u = new User();

    //Name and email are required.
    if(FirstName != null && FirstName != '' && LastName != null && LastName != ''){
        if(Email != null && Email != ''){
            u.FirstName =FirstName;
            u.LastName =LastName;
            u.Username = Email;
            u.Email = Email;
            u.Phone = Phone;
            u.CommunityNickname = LastName;             
            system.debug('## createPersonAccountPortalUser: user =' + u);
            system.debug('## createPersonAccountPortalUser: PortalOwnerId = ' + PortalOwnerId);
            String strRecTypeId = queryForPersonRecType();
            try{
                userId = Site.createPersonAccountPortalUser(u, PortalOwnerId, 'testpassword');
                system.debug('## createPersonAccountPortalUser: userId = ' + userId);
                mResponseMap.put(KeyId, userId);
                UtilityMap.appendValue(KeyStatus, SuccessNewPersonAccount, mResponseMap);
                return userId;                                      
            }catch(Exception e){
                UtilityMap.appendValue(KeyError, FailureNewPersonAccount, mResponseMap);
                mResponseMap.put(KeyErrorMessage, EncodingUtil.urlEncode(e.getMessage(), 'UTF-8'));
                return null;
            }                               
        }else{UtilityMap.appendValue(KeyError, EmailErr, mResponseMap);}            
    }else{UtilityMap.appendValue(KeyError, NamesRequired, mResponseMap);}
    return userId;      
}

I have also tried running the following code as anonymous apex in the developer console and I still get a null returned.


User u = new User();
u.FirstName ='FirstName';
u.LastName ='LastName';
u.Username = 'testuser';
u.Email = '[email protected]';
u.Phone = 'Phone';
u.CommunityNickname = 'LastName';
String userId = Site.createPersonAccountPortalUser(u, Label.B2C_Portal_Person_Account_Owner_Id, 'testpass');
system.debug('user Id = ' + userId);

What am I doing wrong?

For reference here is my visualforce page

<apex:page showHeader="false" sidebar="false" controller="ServiceRegistrationController" action="{!createRegistration}" contentType="application/json">
<apex:outputText value="{!response}" escape="false"/>

13
  • How are you getting PortalOwnerId? Are you able to manually create a portal user with that owner?
    – metadaddy
    Oct 9, 2012 at 14:54
  • I'm defining that as a hard coded value from a custom label so it can be changed in-life. Oct 9, 2012 at 14:56
  • Have you confirmed that you are able to manually create a portal user with that owner?
    – metadaddy
    Oct 9, 2012 at 15:01
  • Yes I have just tested that and it works OK through the salesforce UI. Oct 9, 2012 at 15:06
  • I'm stumped - I'll ask the gurus in the Portal team...
    – metadaddy
    Oct 9, 2012 at 21:50

1 Answer 1

3

I found some further information here: Provisioning Customer Portal Users with Apex

This post suggests that the problem is that you cannot create a contact and a user record in the same APEX transaction. Doing so is called mixed DML and is not allowed. Therefore if you must create a contact and user at the same time the only way to do so is for one of them to be created asynchronously via a method marked with the @future annotation.

This is the method I have used.


    //Async method, using @future, to create the User record and associate it to the previously created Contact
    //This uses @future because you can not have mixed DML operations for standard objects (Account, Contact) and Setup objects(User)
    @future public static void createUser(String contactId, String email, String firstName, String lastName, String userName, String profileId) {
        Database.DMLOptions dmo = new Database.DMLOptions();
        dmo.EmailHeader.triggerUserEmail = true;
        //take the first few characters of the username for the alias
        String alias = userName.substring(0, 7);
        User u = new User(alias = alias, email=email, 
            emailencodingkey=EmailEncoding, lastname=lastname, languagelocalekey=LanguageLocaleKey, 
            localesidkey=LocaleSidKey, profileid = profileId, contactId=contactId,
            timezonesidkey=TimeZoneSidKey, username=username);

        u.setOptions(dmo);
        insert u;
    }

This appears to be working better than my previous attempt. The error messages now show up in the Apex Jobs page (Administration Setup > Monitoring > Apex Jobs) which makes it easier to debug than the silence that the first attempt gave.

2
  • So are you not using the createPersonAccountPortalUser method at all now?
    – Phil B
    Dec 13, 2012 at 19:53
  • No I gave up on that method. Dec 20, 2012 at 13:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .