Веб-Api в .net core не может найти необходимую службу для GraphQL

#c# #graphql

Вопрос:

У меня есть api, над которым я работаю, и я продолжаю сталкиваться с этой ошибкой:

InnerException
{«Требуется служба для типа GraphQL.Types.Тип интерфейса1[CardSortApiV3.Domain.DTO.ContactDTO] не найден»} Система.Исключение {Система.Исключение недействительной операции}

У меня есть следующий код в их соответствующих файлах: StartUp.cs

 public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddScoped<IDocumentExecuter, DocumentExecuter>();
    services.AddScoped<IDocumentWriter, DocumentWriter>();
    services.AddScoped<ProjectQuery>();
    services.AddScoped<ContactQuery>();
    services.AddScoped<MainQuery>();
    services.AddScoped<ProjectType>();
    services.AddScoped<ContactType>();
    services.AddScoped<ContactDTO>();
    services.AddScoped<ISchema, GraphQLProjectSchema>();
    services.AddDbContext<cardsortsoftwaresContext>();
    services.AddScoped<IProjectService, ProjectService>();
    services.AddScoped<IProjectRepository, ProjectRepository>();
}
 

ContactQuery.cs

 public class ContactQuery : ObjectGraphType
{
    public ContactQuery()
    {
        int id = 0;
        Field<ListGraphType<ContactType>>(
            name: "contacts", resolve: context =>
            {
                return /*projectService.GetProjects()*/ null;
            });
        Field<ContactType>(
            name: "project",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
            {
                id = (int)context.Arguments["id"].Value;
                return /*projectService.GetProjectById(id)*/ null;
            });
    }
}
 

ProjectQuery.cs

 public class ProjectQuery : ObjectGraphType<object>
{
    public ProjectQuery(IProjectService projectService)
    {
        Name = "Query";
        int id = 0;
        Field<ListGraphType<ProjectType>>(
            name: "projects", resolve: context =>
            {
                return projectService.GetProjects();
            });
        Field<ProjectType>(
            name: "project",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
            {
                id = (int)context.Arguments["id"].Value;
                return projectService.GetProjectById(id);
            });
    }
}
 

MainQuery.cs

 public MainQuery()
{
    Field<ProjectQuery>("projects", resolve:context =>
    {
        return new {};
    });
    Field<ContactQuery>("contacts", resolve: context =>
    {
        return new {};
    });
}
 

Schema.cs

 public class GraphQLProjectSchema:Schema, ISchema
{
    public GraphQLProjectSchema(IServiceProvider resolver):base(resolver)
    {
        Query = resolver.GetService<MainQuery>();
    }
}
 

Я провел последние 4 часа, исследуя и ища ответы, но ничего не работает. Все работает до тех пор, пока я не попытаюсь добавить ссылку Contact на a Project .

Любая помощь будет серьезно оценена.

ПРАВКА: Сегодня утром я понял, что это могло бы помочь, если бы я также предоставил файлы типов.

ContactType.cs

 public class ContactType : ObjectGraphType<ContactDTO>
{
    public ContactType()
    {
        Name = "Contact";
        Field(_ => _.Id).Description("Contact Id");
        Field(_ => _.FullName).Description("Contact Name");
        Field(_ => _.Email).Description("Contact Email");
        Field(_ => _.Phone).Description("Phone number for contact");
    }
}
 

Тип проекта.cs

 public class ProjectType : ObjectGraphType<ProjectDTO>
{
    public ProjectType()
    {
        Name = "Project";
        Field(_ => _.Id).Description("Project Id");
        Field(_ => _.Title).Description("Project Title");
        Field(_ => _.Description).Description("Project Description");
        Field(_ => _.ConfirmationCode).Description("Project Confirmation Code");
        Field(_ => _.Options).Description("Project Options ("As a comma separated list")");
        Field(_ => _.ProjectStatus).Description("Project Status ("As an integer")");
        Field(_ => _.CreatedTime).Description("Project Creation Time");
        Field(_ => _.UpdatedTime).Description("Project Update Time");
        Field(_ => _.EstimatedCompletion).Description("Estimated Completion Date");
        Field<InterfaceGraphType<ContactDTO>>("contact", "The contact that requested this project");
    }
}
 

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

1. Существует ли несколько определений ContactDTO ? Возможно, добавил не тот?

2. @JHBonarius Нет, есть только одно определение для ContactDTO

3. Для справки, он ломается при последнем Field звонке в ProjectType

Ответ №1:

Я действительно нашел ответ, хотя поначалу казалось, что это не сработает.

Startup.cs

     public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddScoped<IDocumentExecuter, DocumentExecuter>();
        services.AddScoped<IDocumentWriter, DocumentWriter>();
        services.AddScoped<ProjectQuery>();
        services.AddScoped<ContactQuery>();
        services.AddScoped<MainQuery>();
        services.AddScoped<ProjectType>();
        services.AddScoped<ContactType>(); // This was already provided
        services.AddScoped<ISchema, GraphQLProjectSchema>();
        services.AddDbContext<cardsortsoftwaresContext>();
        services.AddScoped<IProjectService, ProjectService>();
        services.AddScoped<IProjectRepository, ProjectRepository>();
    }
 

Затем в файле ProjectType.cs

     public ProjectType()
    {
        Name = "Project";
        Field(_ => _.Id).Description("Project Id");
        Field(_ => _.Title).Description("Project Title");
        Field(_ => _.Description).Description("Project Description");
        Field(_ => _.ConfirmationCode).Description("Project Confirmation Code");
        Field(_ => _.Options).Description("Project Options ("As a comma separated list")");
        Field(_ => _.ProjectStatus).Description("Project Status ("As an integer")");
        Field(_ => _.CreatedTime).Description("Project Creation Time");
        Field(_ => _.UpdatedTime).Description("Project Update Time");
        Field(_ => _.EstimatedCompletion).Description("Estimated Completion Date");
        /* Notice here that I am now requesting ContactType rather than ObjectGraphType<ContactDTO>*/
        Field<ContactType>("contact", "The contact that requested this project");
    }
 

Поскольку я указал тип контакта для ConfigureServices метода, DI смог его разрешить. Я не могу с уверенностью сказать, что понимаю, почему это работает, но я знаю, что для того, чтобы предоставить ссылку от одного типа к другому, вы хотите запросить их напрямую как типы, которые указаны в ConfigureServices .

Ответ №2:

На самом деле, вы используете GraphQL для извлечения данных? вы можете посмотреть NReco.GraphQL, чтобы сделать это из коробки. Нет необходимости настраивать классы/распознаватели для каждого определения схемы (достаточно просто определить его один раз в файле JSON).