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

Json serialization error when updating user in Azure AD via GRAPH

我正在使用 Microsoft.Graph 库 here 更新 Azure AD 中的用户。这对某些用户有效,但对其他用户无效。我的代码如下所示:

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

AdUser class 相当基础,仅包括要更新的属性:

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; }
}

对于要更新的​​前三个用户,这很好用。在第四个用户上,我收到一个通用的 AggregateException 消息,"Exception of type 'Microsoft.Graph.ServiceException' was thrown."

启动 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"
    }
  }
}

如果我单步执行代码,我可以看到错误发生在这一行:

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

这总是发生在同一个用户身上。有什么想法吗?

谢谢!!!

更新 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;
}

更新二: 请求和响应如下所示。请注意,我没有构建 JSON,SDK 会为我构建。我知道请求中的重复键:

请求:

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}

响应:

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

您请求中的 json 数据无效,它添加了重复的 属性、givenNamesurname如下图:

请删除重复的并确保 json 数据有效您可以从 here.

检查它

要更新用户,我们只需要提供我们想要的更改字段。例如,这里是为用户更新部门的示例,供您参考:

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

我已将此归结为我们将 JSON 数据反序列化到各自模型的方式中的错误。模型属性归因于标准 .NET 数据协定。但是,我们使用 NewtonSoft 来完成实际的 JSON 工作。两者的结合导致属性的空值被错误地放入 AdditionalData 字典 属性(未知值的 "catch-all" 桶)。

下一次 SDK 更新时将发布此问题的修复程序。您可以跟踪它 here 前进。

要在短期内解决此问题,您可以遍历 AdditionalData 字典并删除键与模型上已知 属性 匹配的任何条目。如果您在发送更新之前执行此操作,它应该可以正常工作。

更多详情

可以在我们的 SDK 之外普遍重现此错误。例如:

<!-- 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.
}