Клиенту службы Microsoft Graph не удается ИСПРАВИТЬ пользовательские атрибуты безопасности

Согласно официальной документации Microsoft , можно присвоить значения пользовательских атрибутов безопасности, используя следующий код:

var requestBody = new User
{
    CustomSecurityAttributes = new CustomSecurityAttributeValue
    {
        AdditionalData = new Dictionary<string, object>
        {
            {
                "Engineering" , new 
                {
                    OdataType = "#Microsoft.DirectoryServices.CustomSecurityAttributeValue",
                    ProjectDate = "2022-10-01",
                }
            },
        },
    },
};

var result = await graphClient.Users["{user-id}"].PatchAsync(requestBody);

По-видимому, это C#-эквивалент следующего запроса HTTP PATCH:

PATCH https://graph.microsoft.com/v1.0/users/{id}
Content-type: application/json

{
    "customSecurityAttributes":
    {
        "Engineering":
        {
            "@odata.type":"#Microsoft.DirectoryServices.CustomSecurityAttributeValue",
            "ProjectDate":"2022-10-01"
        }
    }
}

Хотя я успешно использовал Graph Explorer и без происшествий выполнил запрос HTTP PATCH для пользовательских атрибутов безопасности, мой код C# не работает. Вместо этого клиент выдает следующую ошибку:

Microsoft.Graph.Beta.Models.ODataErrors.ODataError: Invalid property 'SalesforceAccountId'.
   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.ThrowIfFailedResponse(HttpResponseMessage response, Dictionary`2 errorMapping, Activity activityForAttributes, CancellationToken cancellationToken)
   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](RequestInformation requestInfo, ParsableFactory`1 factory, Dictionary`2 errorMapping, CancellationToken cancellationToken)
   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](RequestInformation requestInfo, ParsableFactory`1 factory, Dictionary`2 errorMapping, CancellationToken cancellationToken)
   at Microsoft.Graph.Beta.Users.Item.UserItemRequestBuilder.PatchAsync(User body, Action`1 requestConfiguration, CancellationToken cancellationToken)
   at PwsPortal.App.Services.MsGraph.GraphService.AssignAccountIdToUserAsync(String userId, String accountId) in C:\Users\George\source\repos\PwsPortal2\PwsPortal\App\Services\MsGraph\GraphService.cs:line 90
   at PwsPortal.Controllers.SalesforceController.AddSecurityAttributeToUserAsync() in C:\Users\George\source\repos\PwsPortal2\PwsPortal\Controllers\SalesforceController.cs:line 105
   at lambda_method77(Closure, Object)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.InvokeCore(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

*** Headers omitted ***

Однако, как вы можете видеть, мой код почти идентичен примеру Microsoft — метод тот же, отличаются только набор, имя и значение:

var requestBody = new User
{
    CustomSecurityAttributes = new CustomSecurityAttributeValue
    {
        AdditionalData = new Dictionary<string, object>
        {
            {
                "SalesforceAccountId" , new
                {
                    ODataType = "#Microsoft.DirectoryServices.CustomSecurityAttributeValue",
                    Id = accountId,
                }
            },
        },
    },
};
await _graphServiceClient.Users[userId].PatchAsync(requestBody);

Мой вопрос: что происходит и как это можно решить? Мне нужно программно добавить значения пользовательских атрибутов безопасности, и, очевидно, клиент службы графов в этом случае ведет себя не так, как предполагалось. Что я делаю не так?

Не могли бы вы помочь подтвердить, сработало ли это при использовании примеров кодов? Если примеры кодов сработали, пробовали ли вы изменить Id на другое имя свойства, например AccId?

Tiny Wang 10.05.2024 09:03

@TinyWang Я попробовал образец - он тоже не работает с той же ошибкой («Microsoft.Graph.Beta.Models.ODataErrors.ODataError: Недопустимое свойство 'Engineering'»). Он даже не доходит до стадии, когда клиент службы фактически выполняет запрос PATCH — он терпит неудачу в самом методе.

Scarecrow Krone 10.05.2024 15:16
I have successfully utilised the Graph Explorer and run an HTTP PATCH request for custom security attributes without incident --> Могу ли я это понять, поскольку у вас уже есть правильное разрешение API и ваша учетная запись имеет правильную роль пользователя? И у вас возникают проблемы только в SDK? Если да, то я заметил, что в стеке вызовов есть Microsoft.Graph.Beta похоже на бета-версию SDK. Не могли бы вы переключиться на версию V1.0?
Tiny Wang 10.05.2024 15:57

@TinyWang Да, разрешения не являются проблемой, поскольку я могу использовать обозреватель графов для запуска запроса без проблем, я просто не могу запустить запрос на C# с помощью клиента службы Graph. Я перешел на версию 1.0, и она все еще не работает.

Scarecrow Krone 10.05.2024 16:51

извините, тогда у меня нет других идей, так как у меня нет тестового ресурса, я не могу тестировать на своей стороне.

Tiny Wang 11.05.2024 07:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это подтвержденная проблема с генератором фрагментов SDK и тем, как он сериализует/десериализует анонимные типы.

На GitHub также есть решение , но оно запутанное, неинтуитивное и, вероятно, не очень надежное:

var requestBody = new User
{
    CustomSecurityAttributes = new CustomSecurityAttributeValue
    {
        AdditionalData = new Dictionary<string, object>
        {
            {
                "Engineering" , new CustomSecurityAttributeValue() // Specify the object rather than using an anonymous type
                {
                    OdataType = "#Microsoft.DirectoryServices.CustomSecurityAttributeValue",
                    AdditionalData = new Dictionary<string, object> { // Put the custom attribute key and value into the AdditionalData property
                        { "projectDate", "2022-10-01" }
                    },
                }
            },
        },
    },
};

Надеюсь, это поможет, если кто-то ищет ту же проблему. Это было актуально на данный момент и в Graph SDK 5.52.0.

Другие вопросы по теме