Skip to content

rodolfotorres/graphql-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

.NET core mvc + GraphQL Conventions

Introduction

This is a small tutorial on how to integrate GraphQL Conventions with a .net core mvc app.

Instructions

Url

Query

query _($teamId: String!) {
  viewer {
    team(id: $teamId) {
      id
      name
    }
  }
}

Variables

{"teamId":"2252141"}

Result

{
  "data": {
    "viewer": {
      "team": {
        "id": "VGVhbToyMjUyMTQx",
        "name": "Namefor: 2252141"
      }
    }
  }
}

Structure

On this example we want to expose Team information

Controller

[Route("api/[controller]")]
public class GraphQLController : Controller
{
    private readonly ITeamSchema _teamSchema;

    public GraphQLController(ITeamSchema teamSchema)
    {
        _teamSchema = teamSchema;
    }

    [HttpPost("query")]
    public async Task<IActionResult> Query()
    {
        StreamReader reader = new StreamReader(Request.Body);
        var query = await reader.ReadToEndAsync();
        var result = await _teamSchema.ProcessRequest(GraphQLWeb.Request.New(query));
        return result.HasErrors ? (IActionResult)BadRequest(result) : Ok(result.Body);
    }
}

Schema

public class TeamSchema : ITeamSchema
{
    private readonly IRequestHandler _requestHandler;
    public TeamSchema(IDependencyInjector dependencyInjector)
    {
        _requestHandler = RequestHandler
            .New()
            .WithQuery<TeamsQuery>()
            .WithDependencyInjector(dependencyInjector)
            .WithoutValidation()
            .Generate();
    }
    public Task<Response> ProcessRequest(Request request) => _requestHandler.ProcessRequest(request, new UserContext());
}

Query

[ImplementViewer(OperationType.Query)]
public class TeamsQuery
{
    private readonly ITeamRepository _teamRepository;

    public TeamsQuery(ITeamRepository teamRepository)
    {
        _teamRepository = teamRepository;
    }
    [Description("Team Query")]
    public async Task<Team> Team(NonNull<string> id)
    {
        var teamDto = await _teamRepository.GetTeamById(id);
        return new Team(teamDto);
    }
}

Repository

public class TeamRepository : ITeamRepository
{
    public Task<TeamDto> GetTeamById(string id) => Task.FromResult(new TeamDto { Id = id, Name = $"Namefor: {id}"});
}

Type

public class Team : INode
{
    private readonly TeamDto _dto;

    public Team(TeamDto dto)
    {
        _dto = dto;
    }
    [Description("Id")]
    public Id Id => Id.New<Team>(_dto.Id);

    [Description("Name")]
    public string Name => _dto.Name;
}

Dependency Injection

Conventions needs a DI to resolve dependencies for graphql types. In this example Team type needs the ITeamRepository that is registered against .net core DI. We provide a wrapper for .net core IServiceProvider

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddSingleton<IDependencyInjector, GraphQLDependencyInjector>()
        .AddSingleton<ITeamRepository, TeamRepository>()
        .AddSingleton<TeamsQuery, TeamsQuery>()
        .AddSingleton<ITeamSchema, TeamSchema>()
        .AddMvc();
}

public class GraphQLDependencyInjector : IDependencyInjector
{
    private readonly IServiceProvider _serviceProvider;

    public GraphQLDependencyInjector(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public object Resolve(TypeInfo typeInfo) => _serviceProvider.GetService(typeInfo.AsType());
}

Soon

  • Data loader example
  • Subscription for members

About

POC for .net core + graphql conventions

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages