This is a small tutorial on how to integrate GraphQL Conventions with a .net core mvc app.
Url
- API: http://localhost:5000/api/graphql/query
- Frontend: http://localhost:5000
Query
query _($teamId: String!) {
viewer {
team(id: $teamId) {
id
name
}
}
}
Variables
{"teamId":"2252141"}
Result
{
"data": {
"viewer": {
"team": {
"id": "VGVhbToyMjUyMTQx",
"name": "Namefor: 2252141"
}
}
}
}
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;
}
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());
}
- Data loader example
- Subscription for members