4

I am having such a bad time trying to figure this out. I'm trying to add a user to a group by posting to:

_api/web/sitegroups(8)/users  

The posted data looks like this:

{ '__metadata': { 'type': 'SP.User' }, 'LoginName' : 'i:0#.w|domain\\user' }

I get Bad Request 400 and I have no idea what is wrong.

public void AddUserToGroup()
            {
                string requestPath = "/_api/web/sitegroups(8)/users";
                string userPostBody = "{ '__metadata': { 'type': 'SP.User' }, 'LoginName':'i:0#.w|domain\\user' }";
                ExecuteAuthorizedPostRequest(requestPath, userPostBody);
            }

        private HttpWebResponse ExecuteAuthorizedPostRequest(string requestPath, string postBody)
        { 
            string formDigestValue = GetFormDigestValue();
            HttpWebRequest request = PreparePostRequest(requestPath, formDigestValue, postBody);

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            return response;
        }

        private HttpWebRequest PreparePostRequest(string requestPath, string formDigestValue, string postBody)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + requestPath);
            request.Method = "POST";
            request.ContentType = "application/json;odata=verbose";
            request.Accept = "application/json;odata=verbose";
            request.Headers.Add("X-RequestDigest", formDigestValue);
            request.UseDefaultCredentials = true;
            request.ContentLength = postBody.Length;

            byte[] postData = Encoding.ASCII.GetBytes(postBody);

            Stream requestStream = request.GetRequestStream();
            requestStream.Write(postData, 0, postData.Length);
            requestStream.Close();

            return request;
        }
  • Have you looked at the respone message content? I think it might be helpful for you. If you are uncertain where to find it consider using Fiddler, Wireshark or similar. – eirikb Nov 14 '14 at 11:03
  • @robert-lindgren did you just accidentally solve the question when cleaning/editing it (adding tow backslashes)? :D – eirikb Nov 14 '14 at 12:37
  • @eirikb, sorry but the double-backslashes was there all the time (but not visible due to invalid markup) :) – Robert Lindgren Nov 14 '14 at 14:12
6

Fiddler is your friend. If you watch the traffic (response) you see the real error message:

Invalid JSON. An unrecognized escape sequence '\u' was found in a JSON string value.

(where 'u' is the first character of the user name)

You should double-escape the backslash \, once for C# and once for JSON. That means i:0#.w|domain\\\\user (four backslashes!) instead of i:0#.w|domain\\user (two backslashes). The same is true for JavaScript.

The posted data should be (two backslashes!):

{ '__metadata': { 'type': 'SP.User' }, 'LoginName' : 'i:0#.w|domain\\user' }
  • You are welcome! I'm more than happy that my suggestion helped. :-) – pholpar Nov 14 '14 at 12:05
4

I'll just add this as an alternative:
If you serialize the JSON, e.g., with JSON.NET, you would not have stumbled upon the problem @pholpar pointed out to you.

Like this:

string loginName = ...;
var postBody = JsonConvert.SerializeObject(new
{
    __metadata = new
    {
        type = "SP.User"
    },
    LoginName = loginName
});
  • For what it is worth, the JavaScriptSerializer class that is part of the System.Web.Extensions assembly creates identical JSON in this case without a third party dependency. – Goyuix Dec 3 '14 at 15:51
3

Just for the sake of completeness, according to Using WCF Data Service With Restricted Characters as Keys:

the symbols %,&,*,:,<,>,+,#, /, ?,\ are considered as "special" in WCF Data Service

In order to avoid such kind of errors, the serialization of POCO is commonly used.

Examples

var loginName = "i:0#.w|domain\\user";

var userPayload = new
{
      __metadata = new
      {
         type = "SP.User"
      },
      LoginName = loginName
};

Using JSON.NET

var postData = JsonConvert.SerializeObject(userPayload);

Using JavaScriptSerializer

var serializer = new JavaScriptSerializer();
var postData = serializer.Serialize(userPayload);
  • I just have to ask; how is restricted characters for WCF related to post body in REST? You don't need to escape them in the post body. Maybe if you use them as keys in a JSON object, but I don't even know how to test that (and that is not what OP has anyway) – eirikb Nov 14 '14 at 13:45
  • @eirikb, thank you for the comment! ..because if you take a look at the property LoginName in postBody string after the serialization (at your example it is at line: postBody = JsonConvert.SerializeObject) you will notice that the value is escaped – Vadim Gremyachev Nov 14 '14 at 14:41
  • 1
    Yeah ok now I see what you mean. JSON itself will of course use backslash to escape (ref JSON.stringify('\\')). But still, the link you provide is about URLs and URIs and not post body, and not even JSON, which is why I was confused :) – eirikb Nov 14 '14 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.