简体   繁体   English

通过GRAPH更新Azure AD中的用户时出现Json序列化错误

[英]Json serialization error when updating user in Azure AD via GRAPH

I am using the Microsoft.Graph library here to update a user in Azure AD. 我在这里使用Microsoft.Graph库来更新Azure AD中的用户。 This works for some users, but fails for others. 这对某些用户有效,但对其他用户无效。 My code looks like this: 我的代码看起来像这样:

public async Task<User> UpdateUser(AdUser adUser)
{
    var graphServiceClient = new GraphServiceClient(_azureAuthenticationProvider);

    var user = await GetUser(adUser.UserPrincipalName);

    user.GivenName = adUser.GivenName;
    user.Surname = adUser.LastName;
    user.DisplayName = adUser.DisplayName;
    user.Department = adUser.Department;
    user.AccountEnabled = adUser.AccountEnabled;

    await graphServiceClient.Users[user.UserPrincipalName].Request().UpdateAsync(user);
    await UpdateUserGroups(adUser);

    return await GetUser(adUser.UserPrincipalName);
}

The AdUser class is fairly basic and just includes the properties to update: AdUser类非常基础,只包含要更新的属性:

public class AdUser
{
    public string UserPrincipalName { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string GivenName { get; set; }
    public string LastName { get; set; }
    public string DisplayName { get; set; }
    public string Department { get; set; }
    public List<string> OldGroups { get; set; }
    public List<string> OldRoles { get; set; }
    public List<string> NewGroups { get; set; }
    public List<string> NewRoles { get; set; }
    public bool AccountEnabled { get; set; }
    public bool ForceChangePasswordNextSignIn { get; set; }
}

For the first three users to be updated, this works just fine. 对于要更新的​​前三个用户,这很好用。 On the fourth user, I get a generic AggregateException with the message, "Exception of type 'Microsoft.Graph.ServiceException' was thrown." 在第四个用户上,我得到一个通用的AggregateException,其中包含“抛出类型'Microsoft.Graph.ServiceException'的异常。”

Firing up Fiddler shows the failed request: 解雇Fiddler显示失败的请求:

{
  "error": {
    "code": "InternalServerError",
    "message": "Can not add property department to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.",
    "innerError": {
      "request-id": "b82c4098-6031-40c4-ac6a-4f43746e7b48",
      "date": "2016-07-12T05:55:08"
    }
  }
}

If I step through the code, I can see the error occurs on this line: 如果我单步执行代码,我可以看到此行发生错误:

await graphServiceClient.Users[user.UserPrincipalName].Request().UpdateAsync(user);

This always occurs for the same user. 这始终发生在同一个用户身上。 Any ideas? 有任何想法吗?

Thanks!!! 谢谢!!!

Update 1: For completeness, my GetUser method looks like this: 更新1:为了完整性,我的GetUser方法如下所示:

public const string AdUserFields = "UserPrincipalName,DisplayName,GivenName,Surname,Department,MemberOf,AccountEnabled";

public async Task<User> GetUser(string userPrincipalName, string fields = AdUserFields)
{
    var graphServiceClient = new GraphServiceClient(_azureAuthenticationProvider);

    var user = await graphServiceClient.Users[userPrincipalName].Request().Select(fields).GetAsync();

    return user;
}

Update 2: The request and response looks like this. 更新2:请求和响应如下所示。 Note that I did not construct the JSON, the SDK does that for me. 请注意,我没有构建JSON,SDK为我做了。 I am aware of the duplicate key in the request: 我知道请求中的重复键:

REQUEST: 请求:

PATCH https://graph.microsoft.com/v1.0/users/jane.doe@contoso.onmicrosoft.com HTTP/1.1
SdkVersion: graph-dotnet-1.0.1
Authorization: Bearer <token>
Cache-Control: no-store, no-cache
Content-Type: application/json
Host: graph.microsoft.com
Content-Length: 478
Expect: 100-continue

{"accountEnabled":true,"businessPhones":[],"department":"department","displayName":"Jane Doe (department)","givenName":"Jane","surname":"Doe","userPrincipalName":"jane.doe@contoso.onmicrosoft.com","id":"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa","@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users/$entity","givenName":null,"jobTitle":null,"mail":null,"mobilePhone":null,"officeLocation":null,"preferredLanguage":null,"surname":null}

RESPONSE: 响应:

HTTP/1.1 500 Internal Server Error
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.5
request-id: 2c0437b3-2438-4a34-bf70-937bec2143d1
client-request-id: 2c0437b3-2438-4a34-bf70-937bec2143d1
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"SouthEast Asia","Slice":"SliceB","ScaleUnit":"001","Host":"AGSFE_IN_0","ADSiteName":"SIN"}}
Duration: 30.6384
X-Powered-By: ASP.NET
Date: Wed, 13 Jul 2016 03:08:14 GMT

142
{
  "error": {
    "code": "InternalServerError",
    "message": "Can not add property givenName to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.",
    "innerError": {
      "request-id": "2c0437b3-2438-4a34-bf70-937bec2143d1",
      "date": "2016-07-13T03:08:14"
    }
  }
}
0

I have tracked this down to a bug in the way we are de-serializing the JSON data into their respective models. 我已将此跟踪到我们将JSON数据反序列化为各自模型的方式中的错误。 The model properties are attributed with standard .NET data contracts. 模型属性归因于标准.NET数据协定。 However, we use NewtonSoft to do the actual JSON work. 但是,我们使用NewtonSoft来完成实际的JSON工作。 The combination of the two causes null values for properties to be incorrectly placed into the AdditionalData dictionary property (a "catch-all" bucket for unknown values). 两者的组合导致属性的空值被错误地放入AdditionalData字典属性(未知值的“catch-all”存储桶)。

A fix for this issue will be released with the next SDK update. 将在下一次SDK更新时发布此问题的修复程序。 You can track it here moving forward. 你可以在这里跟踪它。

To workaround the issue for the short-term, you can iterate through the AdditionalData dictionary and remove any entry where the key matches a known property on the model. 要解决短期问题,可以遍历AdditionalData字典并删除密钥与模型上的已知属性匹配的任何条目。 If you do this before sending the update, it should work correctly. 如果在发送更新之前执行此操作,则应该可以正常工作。

More Detail 更多详情

It is possible to reproduce this bug generically outside our SDK. 可以在我们的SDK之外一般地重现此错误。 For example: 例如:

<!-- language: c# -->

public class User
{
    [DataMember(EmitDefaultValue = false, IsRequired = false, Name = "name")]
    public string Name { get; set; }

    [DataMember(EmitDefaultValue = false, IsRequired = false, Name = "department")]
    public string Department { get; set; }

    [JsonExtensionData(ReadData = true, WriteData = true)]
    public IDictionary<string, object> AdditionalData { get; set; }
}

void SomeFunction()
{
    string json = @"{ 'name': 'Bob Smith', 'department': null }";
    var user = JsonConvert.DeserializeObject<User>(json);

    // Inspecting user here will show the Name property with the correct
    // value, the Department property with a null value, but will also
    // have a "department = null" key / value pair incorrectly in the
    // AdditionalData property.
}

The json data in you request is invalidate, it added duplicate property, givenName and surname like figure below: 您请求的json数据无效,它添加了重复属性, givenNamesurname如下图所示:

在此输入图像描述 Please remove the duplicate one and ensure the json data is validate you can check it from here . 请删除重复的一个并确保json数据已验证,您可以从此处进行检查。

And to update the user, we only need to provide the changed field we wanted. 要更新用户,我们只需要提供我们想要的更改字段。 For example, here is sample that update the department for the user for your reference: 例如,以下示例为用户更新部门以供参考:

 var user = graphserviceClient.Me.Request();
 var newUser = new User();
 newUser.Department = "dep1";
 var updateUser=await user.UpdateAsync(newUser);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM