diff --git a/src/AspNetCoreMulti/Example/GraphQL.cs b/src/AspNetCoreMulti/Example/GraphQL.cs deleted file mode 100644 index c988986..0000000 --- a/src/AspNetCoreMulti/Example/GraphQL.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using GraphQL.Types; - -namespace Example -{ - public class DogSchema : Schema - { - public DogSchema(IServiceProvider provider, DogQuery query) - : base(provider) - { - Query = query; - } - } - - public class DogQuery : ObjectGraphType - { - public DogQuery() - { - Field("say", resolve: context => "woof woof woof"); - } - } - - public class CatSchema : Schema - { - public CatSchema(IServiceProvider provider, CatQuery query) - : base(provider) - { - Query = query; - } - } - - public class CatQuery : ObjectGraphType - { - public CatQuery() - { - Field("say", resolve: context => "meow meow meow"); - } - } -} diff --git a/src/AspNetCoreMulti/Example/GraphQL/Mutations.cs b/src/AspNetCoreMulti/Example/GraphQL/Mutations.cs new file mode 100644 index 0000000..c16413d --- /dev/null +++ b/src/AspNetCoreMulti/Example/GraphQL/Mutations.cs @@ -0,0 +1,44 @@ +using System; +using Example.Repositories; +using GraphQL; +using GraphQL.Types; +using Microsoft.Extensions.DependencyInjection; + +namespace Example.GraphQL; + +public interface IMutationFieldsProvider +{ + void AddMutationFields(ObjectGraphType objectGraph); +} + +public interface ICatMutation : IMutationFieldsProvider { } + +public class CatBreedUpdateMutation : ICatMutation +{ + private readonly IServiceProvider _serviceProvider; + + public CatBreedUpdateMutation(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public void AddMutationFields(ObjectGraphType objectGraph) + { + var args = new QueryArguments + { + new QueryArgument { Name = "breedName" }, + new QueryArgument { Name = "newBreedName" } + }; + + objectGraph.Field("updateCatBreed", arguments: args, resolve: context => + { + var breed = context.GetArgument("breedName"); + var newBreed = context.GetArgument("newBreedName"); + using var scope = _serviceProvider.CreateScope(); + var catRepository = scope.ServiceProvider.GetRequiredService(); + var result = catRepository.UpdateCatBreedName(breed, newBreed); + + return result; + }); + } +} diff --git a/src/AspNetCoreMulti/Example/GraphQL/Queries.cs b/src/AspNetCoreMulti/Example/GraphQL/Queries.cs new file mode 100644 index 0000000..1b8cba2 --- /dev/null +++ b/src/AspNetCoreMulti/Example/GraphQL/Queries.cs @@ -0,0 +1,83 @@ +using System; +using Example.Repositories; +using GraphQL.Types; +using Microsoft.Extensions.DependencyInjection; + +namespace Example.GraphQL; + +public interface IQueryFieldsProvider +{ + void AddQueryFields(ObjectGraphType objectGraph); +} + +public interface IDogQuery : IQueryFieldsProvider { } + +public interface ICatQuery : IQueryFieldsProvider { } + +public class DogQuery : IDogQuery +{ + private readonly IServiceProvider _serviceProvider; + + public DogQuery(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public void AddQueryFields(ObjectGraphType objectGraph) + { + objectGraph.Field("say", resolve: context => "woof woof woof"); + + objectGraph.Field>>>("dogBreeds", resolve: context => + { + using var scope = _serviceProvider.CreateScope(); + var dogRepository = scope.ServiceProvider.GetRequiredService(); + var dogs = dogRepository.GetDogs(); + return dogs; + }); + } +} + +public class DogImageDetailsQuery : IDogQuery +{ + private readonly IServiceProvider _serviceProvider; + + public DogImageDetailsQuery(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public void AddQueryFields(ObjectGraphType objectGraph) + { + objectGraph.FieldAsync>("dogImageDetails", resolve: async context => + { + using var scope = _serviceProvider.CreateScope(); + var imageDetailsRepository = scope.ServiceProvider.GetRequiredService(); + var imageDetails = await imageDetailsRepository.GetDogImageDetailsAsync(); + return imageDetails; + }); + } +} + +public class CatQuery : ICatQuery +{ + private readonly IServiceProvider _serviceProvider; + + public CatQuery(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public void AddQueryFields(ObjectGraphType objectGraph) + { + objectGraph.Field("say", resolve: context => "meow meow meow"); + + objectGraph.Field>>>("catBreeds", resolve: context => + { + using var scope = _serviceProvider.CreateScope(); + var catRepository = scope.ServiceProvider.GetRequiredService(); + var cats = catRepository.GetCats(); + return cats; + }); + } +} + diff --git a/src/AspNetCoreMulti/Example/GraphQL/RootMutations.cs b/src/AspNetCoreMulti/Example/GraphQL/RootMutations.cs new file mode 100644 index 0000000..fa19252 --- /dev/null +++ b/src/AspNetCoreMulti/Example/GraphQL/RootMutations.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using GraphQL.Types; + +namespace Example.GraphQL; + +public class CatRootMutation : ObjectGraphType +{ + public CatRootMutation(IEnumerable mutations) + { + foreach (var mutation in mutations) + { + mutation.AddMutationFields(this); + } + } +} diff --git a/src/AspNetCoreMulti/Example/GraphQL/RootQueries.cs b/src/AspNetCoreMulti/Example/GraphQL/RootQueries.cs new file mode 100644 index 0000000..6544cb5 --- /dev/null +++ b/src/AspNetCoreMulti/Example/GraphQL/RootQueries.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using GraphQL.Types; + +namespace Example.GraphQL; + +public class DogRootQuery : ObjectGraphType +{ + public DogRootQuery(IEnumerable dogQueries) + { + foreach (var dogQuery in dogQueries) + { + dogQuery.AddQueryFields(this); + } + } +} + +public class CatRootQuery : ObjectGraphType +{ + public CatRootQuery(IEnumerable catQueries) + { + foreach (var catQuery in catQueries) + { + catQuery.AddQueryFields(this); + } + } +} diff --git a/src/AspNetCoreMulti/Example/GraphQL/Schemas.cs b/src/AspNetCoreMulti/Example/GraphQL/Schemas.cs new file mode 100644 index 0000000..6f5712b --- /dev/null +++ b/src/AspNetCoreMulti/Example/GraphQL/Schemas.cs @@ -0,0 +1,23 @@ +using System; +using GraphQL.Types; + +namespace Example.GraphQL; + +public class DogSchema : Schema +{ + public DogSchema(IServiceProvider provider, DogRootQuery query) + : base(provider) + { + Query = query; + } +} + +public class CatSchema : Schema +{ + public CatSchema(IServiceProvider provider, CatRootQuery query, CatRootMutation mutation) + : base(provider) + { + Query = query; + Mutation = mutation; + } +} diff --git a/src/AspNetCoreMulti/Example/GraphQL/Types.cs b/src/AspNetCoreMulti/Example/GraphQL/Types.cs new file mode 100644 index 0000000..bea9d77 --- /dev/null +++ b/src/AspNetCoreMulti/Example/GraphQL/Types.cs @@ -0,0 +1,27 @@ +using GraphQL.Types; + +namespace Example.GraphQL; + +public class DogType : ObjectGraphType +{ + public DogType() + { + Field(x => x.Breed); + } +} + +public class CatType : ObjectGraphType +{ + public CatType() + { + Field(x => x.Breed); + } +} + +public class ImageDetailsType : ObjectGraphType +{ + public ImageDetailsType() + { + Field(x => x.Url); + } +} diff --git a/src/AspNetCoreMulti/Example/GraphQLUserContext.cs b/src/AspNetCoreMulti/Example/GraphQLUserContext.cs index c6661f7..7f85ce9 100644 --- a/src/AspNetCoreMulti/Example/GraphQLUserContext.cs +++ b/src/AspNetCoreMulti/Example/GraphQLUserContext.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Security.Claims; -namespace Example +namespace Example; + +public class GraphQLUserContext : Dictionary { - public class GraphQLUserContext : Dictionary - { - public ClaimsPrincipal User { get; set; } - } + public ClaimsPrincipal User { get; set; } } diff --git a/src/AspNetCoreMulti/Example/Models.cs b/src/AspNetCoreMulti/Example/Models.cs new file mode 100644 index 0000000..0d10ad5 --- /dev/null +++ b/src/AspNetCoreMulti/Example/Models.cs @@ -0,0 +1,21 @@ +namespace Example; + +public interface IBreed +{ + public string Breed { get; set; } +} + +public class Dog : IBreed +{ + public string Breed { get; set; } +} + +public class Cat : IBreed +{ + public string Breed { get; set; } +} + +public class ImageDetails +{ + public string Url { get; set; } +} diff --git a/src/AspNetCoreMulti/Example/Repositories/CatRepository.cs b/src/AspNetCoreMulti/Example/Repositories/CatRepository.cs new file mode 100644 index 0000000..2df263d --- /dev/null +++ b/src/AspNetCoreMulti/Example/Repositories/CatRepository.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Example.Repositories; +public class CatRepository +{ + private static readonly List _cats = new() + { + new Cat { Breed = "Abyssinian" }, + new Cat { Breed = "American Bobtail" }, + new Cat { Breed = "Burmese" } + }; + + public IEnumerable GetCats() => _cats.AsEnumerable(); + + public Cat UpdateCatBreedName(string oldName, string newName) + { + var match = _cats.FirstOrDefault(x => x.Breed == oldName); + if (match == null) + { + throw new System.Exception("Cannot find that cat !"); + } + + match.Breed = newName; + + return match; + } +} diff --git a/src/AspNetCoreMulti/Example/Repositories/DogImageDetailsRepository.cs b/src/AspNetCoreMulti/Example/Repositories/DogImageDetailsRepository.cs new file mode 100644 index 0000000..002dc72 --- /dev/null +++ b/src/AspNetCoreMulti/Example/Repositories/DogImageDetailsRepository.cs @@ -0,0 +1,41 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Example.Repositories; +public class DogImageDetailsRepository +{ + private readonly IHttpClientFactory _httpClientFactory; + + public DogImageDetailsRepository(IHttpClientFactory httpClientFactory) + { + _httpClientFactory = httpClientFactory; + } + + public async Task GetDogImageDetailsAsync() + { + try + { + var client = _httpClientFactory.CreateClient("DogsApi"); + var result = await client.GetStringAsync("api/breeds/image/random"); + var apiResponse = JsonSerializer.Deserialize(result); + + return new ImageDetails { Url = apiResponse.Message }; + } + catch (Exception ex) + { + return new ImageDetails { Url = ex.Message }; + } + } + + private class DogsImageApiResponse + { + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonPropertyName("message")] + public string Message { get; set; } + } +} diff --git a/src/AspNetCoreMulti/Example/Repositories/DogRepository.cs b/src/AspNetCoreMulti/Example/Repositories/DogRepository.cs new file mode 100644 index 0000000..28788e3 --- /dev/null +++ b/src/AspNetCoreMulti/Example/Repositories/DogRepository.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Example.Repositories; +public class DogRepository +{ + private static readonly List _dogs = new() + { + new Dog { Breed = "Doberman" }, + new Dog { Breed = "Pit Bull" }, + new Dog { Breed = "German Shepard" } + }; + + public IEnumerable GetDogs() => _dogs.AsEnumerable(); +} diff --git a/src/AspNetCoreMulti/Example/Startup.cs b/src/AspNetCoreMulti/Example/Startup.cs index 10c09d2..f6d94a6 100644 --- a/src/AspNetCoreMulti/Example/Startup.cs +++ b/src/AspNetCoreMulti/Example/Startup.cs @@ -1,3 +1,5 @@ +using Example.GraphQL; +using Example.Repositories; using GraphQL; using GraphQL.MicrosoftDI; using GraphQL.Server; @@ -15,6 +17,15 @@ public class Startup { public void ConfigureServices(IServiceCollection services) { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddGraphQL(b => b .AddHttpMiddleware() .AddHttpMiddleware() @@ -27,6 +38,7 @@ public void ConfigureServices(IServiceCollection services) services.AddLogging(builder => builder.AddConsole()); services.AddHttpContextAccessor(); + services.AddHttpClient("DogsApi", x => x.BaseAddress = new System.Uri("https://dog.ceo/")); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env)