In-Process API GroupUserMembers.Create GET Works, POST Fails

I'm putting together a Plugin handle some data and then add a user to a group programmatically. I'm using a Widget to call the method on a page. When I send the data via querystring everything works fine. When I send it via POST everything works except for the call to Telligent.Evolution.Extensibility.Api.Version1.PublicApi.GroupUserMembers.Create(). Both methods pass in identical data to the Create method, but only when using GET does it actually add the user to the group. Using POST it returns a null GroupUser.

Is this expected behavior? Should you not be able to post to a Page and use InProcess calls? If that's the case, what is a better way to go about doing this?

  • Are you creating a platform C# Plugin (Implementing the IPlugin Interface)??

    When you post It may pass in the context of the accessing user that does not have permissions to add themself to the group...  Are you explicitly changing the contextual user in your plugin?

  • In reply to Luke D:

    Thanks for the quick reply,

    Yes, I am creating a C# Plugin implementing the IPlugin interface. I'm not changing the contextual user though  - which does explain that behaviour.

    That said, how do you change the contextual user in code?

  • In reply to Chad L:

    CSContext.Current.User = <Your User Object>

    Just be sure to switch it back when you're done - with a try/catch/finally

  • In reply to Luke D:

     public class JoinGroupAction
        {
            /// <summary>
            /// Adds a user as a member to the specified group.
            /// </summary>
            /// <param name="userId"></param>
            /// <param name="groupId"></param>
            public void Add(int userId, int groupId)
            {
                var user = Evolution.Users.GetUser(userId);
                if (user == null)
                {
                    return;
                }
    
                try
                {
                    SetContextUser();
                    PublicApi.GroupUserMembers.Create(groupId, userId, new GroupUserMembersCreateOptions() {GroupMembershipType = "Member" });
                }
                catch (Exception)
                {
                    //eat exception 
                }
                finally
                {
                    ReverseContextUser(user);
                }
            }
    
            /// <summary>
            /// Set the current user to the community service account.
            /// </summary>
            private void SetContextUser()
            {
                Telligent.Evolution.Components.User serviceAccount = Telligent.Evolution.Users.GetUser(Telligent.Evolution.Users.ServiceUserName);
                CSContext.Current.User = serviceAccount;
            }
    
            /// <summary>
            /// Reverse the current context user back to the current contextual user.
            /// </summary>
            /// <param name="user"></param>
            private void ReverseContextUser(Telligent.Evolution.Components.User user)
            {
                CSContext.Current.User = user;
            }
    
        }
  • In reply to Luke D:

    Doing that is a really bad idea, if done wrong you can create many problems.  Also its very unsupported and not upgrade safe.  At least in 7.6 this is available in the public API.

    PublicApi.Users.RunAsUser(user,Action) where action is the delegate code to be run under the user context

  • In reply to Patrick Mason:

    Interesting as this was created for us by Telligent Professional Services :)

  • In reply to Luke D:

    The Extensibility/API rules still apply, however I would suspect that your agreement would mean support falls to them in the event of any issues.(Speculation of course)

  • In reply to Patrick Mason:

    Thanks Patrick - I may have to update some of our code to use the new PublicApi implementation..

  • In reply to Luke D:

    Patrick, The site I'm building this one for is currently running on 7.1 - it doesn't look like RunAsUser was implemented there yet. Luke's code does work however.

    What would the recommended approach be for a 7.1 site? We're using some third party plugins that may not be fully supported in 7.6.

    Thanks

  • In reply to Chad L:

    On 7.1, you can replicate the RunAs method with the something like the following (note, I typed this straight into the forurm - there may be some typos etc.): 

    \\ DO NOT USE THE FOLLOWING CODE ON VERSIONS 7.6 OR HIGHER 
    \\ INSTEAD USE PublicApi.Users.RunAs(...) WHICH PROVIDES THE SAME FUNCTIONALITY THROUGH A SUPPORTED API
    public static void RunAs(string newUsername, Action work) { User originalUser = CSContext.Current.User try { var user = Users.Get(newUsername); CSContext.Current.User = newUser; work(); } finally { CSContext.Current.User = originalUser; } }

    Whilst this method is very similar to Luke's suggestion, and is no better from using recommended & supported APIs, it does make it easier for you to get onto the supported path once you upgrade to 7.6 or higher.

    You could even add this as an extension method for PublicApi.Users then all you need to do after upgrading to 7.6 is remove the extension class and recompile :)

  • In reply to Alex Crome:

    To do this supported in 7.1 you can use the REST Api and use impersonation, that is supported and upgrade safe.  You can choose to change it later if you like but will not be required.

    I still highly discourage using CSContext in any capacity, especially for the active user.

  • Thanks everyone for the variety of approaches. For my particular case, I'm going to go with Alex's variation. This particular site is hosted in house so we have enough control of the site to make the upgrade in the future without too much pain from a quick recompile.

    Cheers!

  • In reply to Chad L:

    Alex, how would you go about calling your method in code, for instance, if we wanted to add a specific user to a group - meaning how would you construct your action to do that?

  • In reply to Luke D:

    The same as you would for the public API RunAs method

    PublicApi.Users.RunAsUser("admin", () => {
       //Do stuff here
       //e.g. based on your earlier example
        PublicApi.GroupUserMembers.Create(groupId, userId, new GroupUserMembersCreateOptions{
            GroupMembershipType = "Member"
        });
    });
Related