REST API samples SF v5 - Front- & Back-End Development - Front- & Back-End Development - Progress Community
 Front- & Back-End Development

REST API samples SF v5

  • REST API samples SF v5
  • Hi

    Does anyone have any examples of using the REST API against SF v5? 

    I found the sample client app and have used to be able to login using Claims Auth and can happily list users/roles in my system.

    I now need to be able to create new roles and users. 

    The SVC help file suggests that I need to do PUT to localhost:50049/.../ which seem reasonable except if I'm creating a new role I don't have a roleId to specify.  I tried leaving that out and just using Roles.svc or Roles.svc/?provider=default but anything I've tried always come back with the bad request error suggesting that the URI is incorrect.

    On a related note, does anyone know how to signin and have it force signout if it finds that the username is already logged in (e.g. from a browser session)?

    Thanks
  • Chris,

    Something like Fiddler is going to take you a long way when using the APIs. Fire it up, do whatever it is that you're trying to accomplish in the backend and then watch the calls being made. Sometimes you can just copy the call from Fiddler and paste it right back into your browser or wherever you want it! :)

    If this answer was helpful, please click the "Mark as Featured" link in the top right corner of the post.
  • Hi Chris,

    Did you ever figure out how to force a logout of any existing session for a particular user?  I'm in need of the same functionality, and can't figure it out either.  If you've found a solution, I would appreciate it if you could forward it along to me.

    FYI, I've tried using Charles (my equivalent to Fiddler) to figure out how the web site does it, but there's a lot of extra stuff going on in the HTTP headers that I don't understand, and if I ignore that stuff, I don't see that there's enough info in the HTTP calls to cause a logout.  I've tried lots of things, but nothing has worked.

    S

  • Sorry - I don't finish up this piece of work in the end.  I didn't solve that problem and opted for a different solution using custom membership providers instead.
  • Hello. Has anyone got a resolution for this problem? I am using the IUsers::CreateUser method (~/Sitefinity/Services/Security/Users.svc//create/userId/?provider=provider) but can't get it to work without a 405 Method Not Allowed response. If someone can please post a working sample of a call to CreateUser via the REST API, including authentication, it would be much appreciated.

    Here's my HTTP request (I'm already authenticated in this example using the token returned from ~/Sitefinity/Authenticate):

    PUT myhost/.../ HTTP/1.1
    User-Agent: Fiddler
    Host: myhost
    Authorization: WRAP access_token="mytoken"
    Content-Length: 94
    Content-type: application/json

    "Email":"mynewuseremail@mail.com","Password":"mynewuserpassword","UserName":"mynewusername"

    I'm running SF5.4/IIS7/WindowsServer2008R2/.NET4/x64.

    Thanks,
    Scott
  • Hello Scott,

    We have replied back i9n the support thread you had open on the same issue, you can check our response there. For your convenience I'm copying our response here as well:

    "

    If we take the application provided on Svetla's blog post, and reuse its authentication functionality, we can extend it very easily to support user creation.

    What we need to do is inspect the JSON passed in to the users service when creating users from the Sitefinity backend, and create a C# representation in our application, so we can set these values. Once we have the user object represented, we need to set all the relevant properties of the object, serialize the data and make the PUT request while authenticated.


    I've extended the sample with the above functionality, where we have the


    1. User class:

    Copy Code
    Copy Code
    Copy Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.Serialization;
     
    namespace SFWinformsClient.Model.User
     
               [DataContract]
        public class RolesOfUser
        
                    [DataMember]
            public string ProviderName get; set;
                    [DataMember]
            public string RoleId get; set;
                    [DataMember]
            public string RoleName get; set;
        
     
               [DataContract]
        public class User
        
                    [DataMember]
            public bool AvatarImageSmallerWidth get; set;
                    [DataMember]
            public string AvatarImageUrl get; set;
                    [DataMember]
            public string AvatarThumbnailUrl get; set;
                    [DataMember]
            public string Comment get; set;
                    [DataMember]
            public DateTime CreationDate get; set;
                    [DataMember]
            public string DisplayName get; set;
                    [DataMember]
            public string Email get; set;
                    [DataMember]
            public bool IsApproved get; set;
                    [DataMember]
            public bool IsBackendUser get; set;
                    [DataMember]
            public bool IsLockedOut get; set;
                    [DataMember]
            public bool IsLoggedIn get; set;
                    [DataMember]
            public object LastActivityDate get; set;
                    [DataMember]
            public object LastLockoutDate get; set;
                    [DataMember]
            public object LastLoginDate get; set;
                    [DataMember]
            public DateTime LastPasswordChangedDate get; set;
                    [DataMember]
            public object Password get; set;
                    [DataMember]
            public object PasswordAnswer get; set;
                    [DataMember]
            public string PasswordQuestion get; set;
                    [DataMember]
            public object ProfileData get; set;
                    [DataMember]
            public string ProviderName get; set;
                    [DataMember]
            public string ProviderUserKey get; set;
                    [DataMember]
            public string RoleNamesOfUser get; set;
                    [DataMember]
            public List<RolesOfUser> RolesOfUser get; set;
                    [DataMember]
            public string UserID get; set;
                    [DataMember]
            public string UserName get; set;
                     
        

    2. Extend the client itself by adding an extra button for creating new user.

    Copy Code
    Copy Code
    Copy Code
    # region Create user
     
          private void button2_Click(object sender, EventArgs e)
          
              CreateUser();
          
     
          public void CreateUser()
          
              string responseBody;
     
              var userId = Guid.NewGuid().ToString();
              var userProviderName = "Default";
              //remove the + DateTime.UtcNow.Second.ToString(); it's used for easier testing only!!!
              var firstName = "John " + DateTime.UtcNow.Second.ToString();
              var lastName = "Smith " + DateTime.UtcNow.Second.ToString();
              var userName = "jsmith " + DateTime.UtcNow.Second.ToString();
              var password = "password";
              var mail = "jsmith" + DateTime.UtcNow.Second.ToString() + "@wcf.com";
              var secretQuestion = "";
              var secretAnswer = "";
              var roleName = "BackendUsers";
              var roleProviderName = "AppRoles";
              //get this from SecurityConfig.config
              var backendUsersRoleId = "170fc761-eb01-4d2f-9706-58634fb5de06";
              var rolesForUser = new List<SFWinformsClient.Model.User.RolesOfUser>();
              rolesForUser.Add(new SFWinformsClient.Model.User.RolesOfUser()
              
                  RoleName = roleName,
                  RoleId = backendUsersRoleId,
                  ProviderName = roleProviderName
              );
              var defaultAvataImageUrl = "/SFRes/images/Telerik.Sitefinity.Resources/Images.DefaultPhoto.png";
     
              //set WcfUser data members
              SFWinformsClient.Model.User.User user = new SFWinformsClient.Model.User.User();
              user.AvatarImageSmallerWidth = false;
              user.AvatarImageUrl = defaultAvataImageUrl;
              user.AvatarThumbnailUrl = defaultAvataImageUrl;
              user.Comment = "";
              user.CreationDate = DateTime.UtcNow;
              user.DisplayName = firstName + " " + lastName;
              user.Email = mail;
              user.IsApproved = true;
              user.IsBackendUser = true;
              user.IsLockedOut = false;
              user.IsLoggedIn = false;
              user.LastActivityDate = null;
              user.LastPasswordChangedDate = DateTime.UtcNow;
              user.Password = password;
              user.PasswordAnswer = secretAnswer;
              user.PasswordQuestion = secretQuestion;
              user.ProviderName = userProviderName;
              user.RoleNamesOfUser = roleName;
              user.RolesOfUser = rolesForUser;
              user.UserID = userId;
              user.UserName = userName;
     
              //Pass the default user profile type, it will be resolved automatically
              //Please note currently there is no implementation to create a profile and set the properties by defualt
              //they need to be set additionally from the backend users adminsitration
              user.ProfileData = "\"Telerik.Sitefinity.Security.Model.SitefinityProfile\": ";
     
              JsonSerializerSettings settings = new JsonSerializerSettings();
              settings.DateParseHandling = DateParseHandling.DateTime;
              settings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
              string jsonString = JsonConvert.SerializeObject(user, settings);
     
              //string replacedString = Regex.Replace(jsonString, "\"", "\\\"");
              //replacedString = String.Format("\"0\"", replacedString);
     
              byte[] data = Encoding.UTF8.GetBytes(jsonString);
              helper.CallService(
                  ServiceHelper.UsersUrl +
                  "/create/00000000-0000-0000-0000-000000000000/?provider=" + userProviderName,
                  data,
                  "PUT",
                  out responseBody,
                  "application/json"
                  );
     
     
              textBox1.Text = jsonString;
              var a = responseBody;
              textBox2.Text = a;
     
          
     
          # endregion


    The only details need noting here are how we handle role assignment:


    Copy Code
    Copy Code
    Copy Code
    var roleName = "BackendUsers";
                var roleProviderName = "AppRoles";
                //get this from SecurityConfig.config
                var backendUsersRoleId = "170fc761-eb01-4d2f-9706-58634fb5de06";
                var rolesForUser = new List<SFWinformsClient.Model.User.RolesOfUser>();
                rolesForUser.Add(new SFWinformsClient.Model.User.RolesOfUser()
                
                    RoleName = roleName,
                    RoleId = backendUsersRoleId,
                    ProviderName = roleProviderName
                );

    and pass the correct profile type data:

    Copy Code
    Copy Code
    Copy Code
    //Pass the default user profile type, it will be resolved automatically
                //Please note currently there is no implementation to create a profile and set the properties by defualt
                //they need to be set additionally from the backend users adminsitration
                user.ProfileData = "\"Telerik.Sitefinity.Security.Model.SitefinityProfile\": ";

    I hope you find this information useful. For your convenience please find attached to this reply the modified application.
    "


    All the best,
    Boyan Barnev
    the Telerik team
    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
  • Here's what I did. Seems to work well.

    First create a controller to call into the Sitefinity SecurityManager methods..

    public class UsersController : ApiController
        [HttpPost]
        public UserLoggingReason AuthenticateUser([FromBody] Credentials credentials)
        
            return SecurityManager.AuthenticateUser(credentials);
        
     
        [HttpGet]
        public void Logout()
        
            SecurityManager.Logout();
        
     
        [HttpPost]
        public void ForceLogout([FromBody] Credentials credentials)
        
            SecurityManager.Logout(credentials);
        

    Then here's the client I wrote to do the logging in / out / and force logout when required.

    /// <summary>
        /// Assists accessing secure Sitefinity resources via an HTTP client by running a task wrapped with a log in and log out.
        /// Requires a server side implementation of Authenticate(credentials), Logout(void) and ForceLogout(credentials)
        /// </summary>
        public class SitefinityClient : IDisposable
        
            private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
     
            private readonly SitefinityClientOptions _options;
            private readonly HttpClientHandler _handler;
            private readonly HttpClient _client;
            private readonly object _credentials;
     
            public SitefinityClient(SitefinityClientOptions options)
            
                _options = options;
     
                _credentials = new
                
                    MembershipProvider = "",
                    Persistent = true,
                    UserName = _options.UserName,
                    Password = _options.Password
                ;
     
                _handler = new HttpClientHandler()
                
                    CookieContainer = new CookieContainer()
                ;
     
                _client = new HttpClient(_handler)
                
                    BaseAddress = new Uri(_options.BaseUrl)
                ;
            
     
            /// <summary>
            /// Runs the async task (or lambda) with login and logout.
            /// </summary>
            /// <param name="asyncTask">The asynchronous task (or lambda).</param>
            /// <returns></returns>
            /// <exception cref="System.Exception"></exception>
            public async Task RunWithLoginLogout(Func<HttpClient, Task> asyncTask)
            
                Logger.Info(string.Format("Logging in as 0", _options.UserName));
                var logInResult = await Login();
     
                if (logInResult == UserLoggingReason.UserAlreadyLoggedIn || logInResult == UserLoggingReason.UserLoggedFromDifferentComputer || logInResult == UserLoggingReason.UserLoggedFromDifferentIp)
                
                    Logger.Warn("User already logged in (0). Forcing log out..", logInResult);
                    await ForceLogout();
                    Logger.Info(string.Format("Logging in as 0", _options.UserName));
                    logInResult = await Login();
                
     
                if (logInResult != UserLoggingReason.Success)
                
                    throw new Exception(string.Format("Log in failed: 0", logInResult));
                
     
                ExceptionDispatchInfo taskEx = null;
     
                try
                
                    await asyncTask(_client);
                
                catch (Exception ex)
                
                    taskEx = ExceptionDispatchInfo.Capture(ex);
                
     
                await Logout();
     
                if (taskEx != null)
                
                    taskEx.Throw();
                
            
     
            protected async Task<UserLoggingReason> Login()
            
                var resp = await _client.PostAsJsonAsync(_options.LoginUrl, _credentials);
                resp.EnsureSuccessStatusCode();
                return await resp.Content.ReadAsAsync<UserLoggingReason>();
            
     
            protected async Task ForceLogout()
            
                var resp = await _client.PostAsJsonAsync(_options.ForceLogoutUrl, _credentials);
                resp.EnsureSuccessStatusCode();
            
     
            protected async Task Logout()
            
                Logger.Info("Logging out");
     
                try
                
                    await _client.GetAsync(_options.LogoutUrl);
                
                catch (Exception ex)
                
                    Logger.Error("Log out failed", ex);
                
            
     
            #region IDisposable
     
            public void Dispose()
            
                Dispose(true);
                GC.SuppressFinalize(this);
            
     
            protected virtual void Dispose(bool disposing)
            
                if (disposing)
                
                    if (_client != null)
                    
                        _client.Dispose();
                    
     
                    if (_handler != null)
                    
                        _handler.Dispose();
                    
                
            
     
            #endregion
        

    Then assuming you had a web api method you wanted to post some data to which requires authentication you'd use it (btw in the controller method you can force authentication using the appropriate overload of ServiceUtility.RequestAuthentication)..

    using (var sfClient = new SitefinityClient(options))
        var uploadTask = sfClient.RunWithLoginLogout(async (httpClient) =>
        
            Logger.Info("Uploading...");
            await httpClient.PostAsJsonAsync(options.UploadUrl, data);
        );
     
        uploadTask.Wait();
    Logger.Info("Finished OK");