Как вы можете добавить службу клиента Microsoft Graph в качестве службы MediatR в .NET Core 3.1?

#.net-core #azure-active-directory #microsoft-graph-api #mediator #mediatr

#.net-core #azure-active-directory #microsoft-graph-api #посредник #mediatr

Вопрос:

Итак, у меня есть веб-API .NET Core с собственным локальным контекстом данных, и я хотел бы добавить возможность вызова Microsoft Graph в качестве нисходящего API.

Однако, когда я пытаюсь добавить необходимые свойства для вызова Graph API, я получаю ошибку сборки:

 Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2[Application.Users.Me Query,Microsoft.Graph.User] Lifetime: Transient ImplementationType: Application.Users.Me Handler': Unable to resolve service for type 'Microsoft.Graph.GraphServiceClient' while attempting to activate 'Application.Users.Me Handler'.)
 

Вот мой класс запуска:

 using API.Middleware;
using Application.TestEntities;
using FluentValidation.AspNetCore;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Persistence;
using Microsoft.Identity.Web;

namespace API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<DataContext>(opt =>
            {
                opt.UseSqlite(Configuration.GetConnectionString("DefaultConnection"));
            });
            services.AddCors(opt =>
            {
                opt.AddPolicy("CorsPolicy", policy =>
                {
                    policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:3000");
                });
            });

            services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
                .EnableTokenAcquisitionToCallDownstreamApi()
                .AddInMemoryTokenCaches();

            services.AddMediatR(typeof(List.Handler).Assembly);
            services.AddControllers(opt =>
            {
                var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
                opt.Filters.Add(new AuthorizeFilter(policy));
            })
            .AddFluentValidation(cfg => cfg.RegisterValidatorsFromAssemblyContaining<Create>());
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseMiddleware<ErrorHandlingMiddleware>();
            if (env.IsDevelopment())
            {
                // app.UseDeveloperExceptionPage();
            }

            app.UseCors("CorsPolicy");

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}
 

И мой обработчик приложений для вызова нисходящего потока:

 using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Graph;
using Microsoft.Identity.Web;

namespace Application.Users
{
    public class Me
    {
        public class Query : IRequest<User> { }

        public class Handler : IRequestHandler<Query, User>
        {
            private readonly ITokenAcquisition _tokenAcquisition;
            private readonly GraphServiceClient _graphServiceClient;
            public Handler(ITokenAcquisition tokenAcquisition, GraphServiceClient graphServiceClient)
            {
                _tokenAcquisition = tokenAcquisition;
                _graphServiceClient = graphServiceClient;
            }

            public async Task<User> Handle(Query request, CancellationToken cancellationToken)
            {
                var user = await _graphServiceClient.Me.Request().GetAsync();
                return user;
            }
        }
    }
}
 

Надеюсь, я на правильном пути, но, пожалуйста, дайте мне знать, если это не так.

Комментарии:

1. Надеюсь, вы используете последние пакеты NuGet для вышеуказанных SDK, верно?

2. Я считаю, что да, по большей части.. Для моего проекта API (запуск) У меня есть: Microsoft.EntityFrameworkCore.Design - 3.1.10 Newtonsoft.Json - 12.0.3 Microsoft.Identity.Web - 1.3.0 для приложения у меня есть: MediatR.Extensions.Microsoft.DependencyInjection - 8.1.0 FluentValidation.AspNetCore - 9.2.0 Microsoft.Graph - 3.20.0 Microsoft.Identity.Web - 1.3.0

3. Просто обновил все мои пакеты и избавился от Newtonsoft. Json, поскольку я его больше не использую. Проблема сохраняется.

4. Хорошо, что вы попробовали. В качестве следующих шагов я бы начал изолировать пакеты один за другим и добавлять обратно, чтобы просмотреть, скомпилировать, чтобы увидеть, в какой момент я вижу ошибку. Это поможет вам устранить проблемы с используемыми библиотеками. Кроме того, я хотел бы увидеть какие-либо справочные документы, в которых говорится о точной комбинации, чтобы узнать, сообщается ли о какой-либо известной проблеме.

5. Знаете ли вы, что означает ошибка, которую я получаю?

Ответ №1:

Итак, это был простой недосмотр с моей стороны.

Согласно @franklores, вам необходимо зарегистрировать Microsoft Graph в службах класса запуска:

 services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
 

Добавление следующего в appsettings (области могут отличаться):

   "DownstreamAPI": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "user.read"
  },
 

И обязательно установите Microsoft.Identity.Web.MicrosoftGraph , чтобы включить эту AddMicrosoftGraph() функцию.