Согласно официальной документации 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);
Мой вопрос: что происходит и как это можно решить? Мне нужно программно добавить значения пользовательских атрибутов безопасности, и, очевидно, клиент службы графов в этом случае ведет себя не так, как предполагалось. Что я делаю не так?
@TinyWang Я попробовал образец - он тоже не работает с той же ошибкой («Microsoft.Graph.Beta.Models.ODataErrors.ODataError: Недопустимое свойство 'Engineering'»). Он даже не доходит до стадии, когда клиент службы фактически выполняет запрос PATCH — он терпит неудачу в самом методе.
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?
@TinyWang Да, разрешения не являются проблемой, поскольку я могу использовать обозреватель графов для запуска запроса без проблем, я просто не могу запустить запрос на C# с помощью клиента службы Graph. Я перешел на версию 1.0, и она все еще не работает.
извините, тогда у меня нет других идей, так как у меня нет тестового ресурса, я не могу тестировать на своей стороне.





Это подтвержденная проблема с генератором фрагментов 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.
Не могли бы вы помочь подтвердить, сработало ли это при использовании примеров кодов? Если примеры кодов сработали, пробовали ли вы изменить
Idна другое имя свойства, напримерAccId?