(精华)2020年9月20日 ASP.NET Core WebAPI数据协议GraphQL的使用

首先要使用GraphQL安装三个包

GraphQL
GraphQL.Server.Transports.AspNetCore
GraphQL.Server.Ui.Playground

定义基础类

public class Account
{
    public Guid Id { get; set; }
    public TypeOfAccount Type { get; set; }
    public string Description { get; set; }

    public Guid PersonId { get; set; }
    public Person Person { get; set; }
}

public enum TypeOfAccount
{
    Invalid,
    Free,
    Junior,
    Intermediate
}
public class Person
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    public ICollection<Account> Accounts { get; set; }
}

上下文

public class SampleContext
{
    public List<Person> Persons { get; set; }
    public List<Account> Accounts { get; set; }

    public SampleContext()
    {
        var ids = new[] { Guid.NewGuid(), Guid.NewGuid() };

        Accounts = new List<Account>
        {
            new Account
            {
                Id = Guid.NewGuid(),
                Type = TypeOfAccount.Junior,
                Description = "初级会员",
                PersonId = ids[0]
            },
            new Account
            {
                Id = Guid.NewGuid(),
                Type = TypeOfAccount.Intermediate,
                Description = "中级会员",
                PersonId = ids[1]
            },
            new Account
            {
                Id = Guid.NewGuid(),
                Type = TypeOfAccount.Free,
                Description = "免费会员",
                PersonId = ids[1]
            }
        };


        Persons = new List<Person>
        {
            new Person
            {
                Id = ids[0],
                Name = "张三",
                Address = "北京"
            },
            new Person
            {
                Id = ids[1],
                Name = "李四",
                Address = "上海"
            }
        };
    }
}

仓储

public interface IAccountRepository
{
    IEnumerable<Account> GetAllAccountsPerson(Guid personId);
}
public interface IPersonRepository
{
    IEnumerable<Person> GetAll();
    Person GetById(Guid id);
}
public class AccountRepository : IAccountRepository
{
    private readonly SampleContext _context;

    public AccountRepository(SampleContext context)
    {
        _context = context;
    }

    public IEnumerable<Account> GetAllAccountsPerson(Guid personId)
    {
        return _context.Accounts.Where(a => a.PersonId == personId);
    }
}
public class PersonRepository : IPersonRepository
{
    private readonly SampleContext _context;

    public PersonRepository(SampleContext context)
    {
        _context = context;
    }

    public IEnumerable<Person> GetAll()
    {
        return _context.Persons;
    }

    public Person GetById(Guid id)
    {
        return _context.Persons.SingleOrDefault(p => p.Id == id);
    }
}

GraphQL相关类

public class AccountTypeEnumType : EnumerationGraphType<TypeOfAccount>
{
    public AccountTypeEnumType()
    {
        Name = "Type";
    }
}
public class AccountType : ObjectGraphType<Account>
{
    public AccountType()
    {
        Field(x => x.Id, type: typeof(IdGraphType));
        Field(x => x.Description);
        Field(x => x.PersonId, type: typeof(IdGraphType));
        Field<AccountTypeEnumType>("Type", "Account类型对象的枚举");
    }
}
public class PersonType : ObjectGraphType<Person>
{
    public PersonType(IAccountRepository repository)
    {
        Field(x => x.Id, type: typeof(IdGraphType));
        Field(x => x.Name);
        Field(x => x.Address);
        Field<ListGraphType<AccountType>>(
            name: "accounts",
            resolve: context => repository.GetAllAccountsPerson(context.Source.Id));
    }
}
public class AppSchema: Schema
{
    public AppSchema(IDependencyResolver resolver)
        :base(resolver)
    {
        Query = resolver.Resolve<AppQuery>();
    }
}
public class AppQuery: ObjectGraphType
{
    public AppQuery(IPersonRepository repository)
    {
        Field<ListGraphType<PersonType>>(
            "persons",
            resolve: context => repository.GetAll()
        );

        Field<PersonType>(
            "person",
            arguments: new QueryArguments(new QueryArgument<NonNullGraphType<IdGraphType>> { Name = "personId" }),
            resolve: context =>
            {
                var personId = context.GetArgument<string>("personId");

                if (Guid.TryParse(personId, out var id)) return repository.GetById(id);

                context.Errors.Add(new ExecutionError("错误的GUID格式"));
                return null;
            }
        );
    }
}

在asp.net core中使用

public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddSingleton<SampleContext>();

            services.AddScoped<IPersonRepository, PersonRepository>();
            services.AddScoped<IAccountRepository, AccountRepository>();

            services.AddScoped<IDependencyResolver>(s => new FuncDependencyResolver(s.GetRequiredService));
            services.AddScoped<AppSchema>();
 
            services.AddGraphQL(o => { o.ExposeExceptions = false; })
                .AddGraphTypes(ServiceLifetime.Scoped);

            services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseGraphQL<AppSchema>();
            app.UseGraphQLPlayground(options: new GraphQLPlaygroundOptions());

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

用localhost:5000/ui/playgroud来查看服务页面

客户端的使用如下:

public class PersonConsumer
{
    private readonly IGraphQLClient _client;

    public PersonConsumer(IGraphQLClient client)
    {
        _client = client;
    }

    public async Task<List<Person>> GetAll()
    {
        var query = new GraphQLRequest
        {
            Query = @"
            query personsQuery{
              persons {
                id,
                name,
                address,
                accounts {
                  id,
                  type,
                  description
                }
              }
            }"
        };

        var response = await _client.SendQueryAsync<ResponsePersonCollectionType>(query);
        return response.Data.Persons;
    }

    public async Task<Person> Get(string id)
    {
        var query = new GraphQLRequest
        {
            Query = @"
            query personQuery($personID: ID!) {
              person(personId: $personID) {
                id,
                name,
                address,
                accounts {
                  id,
                  type,
                  description
                }
              }
            }",
            Variables = new { personID = id }
        };

        var response = await _client.SendQueryAsync<ResponsePersonType>(query);
        return response.Data.Person;
    }
}
[Route("api/[controller]")]
[ApiController]
public class PersonController : ControllerBase
{
    private readonly PersonConsumer _personConsumer;

    public PersonController(PersonConsumer personConsumer)
    {
        _personConsumer = personConsumer;
    }

    public async Task<IActionResult> Get()
    {
        var persons = await _personConsumer.GetAll();
        return Ok(persons);
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> Get(string id)
    {
        var person = await _personConsumer.Get(id);
        return Ok(person);
    }
}
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IGraphQLClient>(s =>
            new GraphQLHttpClient(Configuration["GraphQLUri"], new NewtonsoftJsonSerializer()));

        services.AddScoped<PersonConsumer>();

        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:上身试试 返回首页