REST API samples SF v5

Posted by Community Admin on 05-Aug-2018 14:06

REST API samples SF v5

All Replies

Posted by Community Admin on 18-Oct-2012 00:00

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

Posted by Community Admin on 23-Oct-2012 00:00

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.

Posted by Community Admin on 02-Nov-2012 00:00

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

Posted by Community Admin on 13-Nov-2012 00:00

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.

Posted by Community Admin on 03-Apr-2013 00:00

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

Posted by Community Admin on 08-Apr-2013 00:00

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.

Posted by Community Admin on 08-May-2015 00:00

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");

This thread is closed