{"id":13410148,"url":"https://github.com/Develop-Genesis/Graphql-Controller","last_synced_at":"2025-03-14T15:31:56.426Z","repository":{"id":56034389,"uuid":"241213211","full_name":"Develop-Genesis/Graphql-Controller","owner":"Develop-Genesis","description":"A graphql library that integrates nice with .net ","archived":false,"fork":false,"pushed_at":"2020-11-29T23:21:59.000Z","size":511,"stargazers_count":24,"open_issues_count":2,"forks_count":3,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-01T00:57:03.908Z","etag":null,"topics":["apollographql","asp-net-core-graphql","graphql","graphql-controller","graphql-library","persisted-queries"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Develop-Genesis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-17T21:37:52.000Z","updated_at":"2023-11-07T12:53:40.000Z","dependencies_parsed_at":"2022-08-15T11:50:48.821Z","dependency_job_id":null,"html_url":"https://github.com/Develop-Genesis/Graphql-Controller","commit_stats":null,"previous_names":["aleguardiola/graphql-controller"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Develop-Genesis%2FGraphql-Controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Develop-Genesis%2FGraphql-Controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Develop-Genesis%2FGraphql-Controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Develop-Genesis%2FGraphql-Controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Develop-Genesis","download_url":"https://codeload.github.com/Develop-Genesis/Graphql-Controller/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243600686,"owners_count":20317317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apollographql","asp-net-core-graphql","graphql","graphql-controller","graphql-library","persisted-queries"],"created_at":"2024-07-30T20:01:05.215Z","updated_at":"2025-03-14T15:31:55.918Z","avatar_url":"https://github.com/Develop-Genesis.png","language":"C#","funding_links":[],"categories":["GraphQL"],"sub_categories":[],"readme":"\n# Graphql-Controller\n\n![Build](https://dev.azure.com/DevelopGenesis/GraphqlController/_apis/build/status/aleGuardiola.Graphql-Controller?branchName=master)\n\n[![NuGetOrg](https://img.shields.io/nuget/v/GraphqlController)](https://www.nuget.org/packages/GraphqlController/)\n\n![NuGetOrgPre](https://img.shields.io/nuget/vpre/GraphqlController)\n\n[comment]: ![CodeCoverage](https://img.shields.io/azure-devops/coverage/DevelopGenesis/GraphqlController/1/master)\n\nA graphql library that integrates nice with .net \n\n![](exampleCode.gif)\n![](exampleResult.gif)\n\n# Inspiration\nGraphql is the strong typed protocol to pass data, that is the way I see it so my goal\nwith this project is simple, use the strong typed system of .Net to create your Graphql schema \nin a way that you feel it natural.\n\n# Getting Started with Asp.net core\n##### Install nuget package:\n\n` dotnet add package GraphqlController --version 2.0.0 `\n\n` dotnet add package GraphqlController.AspNetCore --version 2.0.0 `\n\n##### How to use it\n\nConfigure your services\n\n```csharp\n\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.AddControllers();\n\n            // Call this two methods\n            services\n                    // Add GraphQlController to your project\n                    .AddGraphQlController()\n                    // Use the current assembly to locate the graphql types \n                    .AddCurrentAssembly(); \n            \n            // Call this to add http enpoint support \n            services.AddGraphQlEndpoint();\n        }        \n    \n```\n\nCreate your graphql types using normal C#, \nmake sure to create them in the same assembly\n\n```csharp\n   \n    public class Student\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }\n        public int Grades { get; set; }\n    }\n\n    public class Teacher\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }        \n    }\n\n```\n\nCreate your root type.\nThe root type is the top of the graph where you can access the data\nand it also represent a graphql api\n\n```csharp\n   \n   // Must have the attribute [RootType]  \n   // and must derive from GraphNodeType\n   [RootType]\n   public class Root : GraphNodeType\n   {\n      public Student Student =\u003e new Student()\n      { \n         Name =\u003e \"Jhon\",\n         LastName =\u003e \"Robinson\",\n         Grades =\u003e 80\n      }\n\n      public Teacher Teacher = new Teacher()\n      {\n         Name =\u003e \"Alejandro\",\n         LastName =\u003e \"Guardiola\"\n      }\n   }\n\n```\n\nAs last step we have to declare what the path for this api should be,\nin our Startup.cs class:\n\n```csharp\n  \n  // use GraphqlController\n  app.UseGraphQLController();\n\n  app.UseEndpoints(endpoints =\u003e\n  {     \n     // Include this line to declare that the root with type Root\n     // will be serving at /graphql \n     endpoints.MapGraphQLEnpoint\u003cRoot\u003e(\"/graphql\");                \n     endpoints.MapControllers();\n  });\n```\n\nIf you run the project and call the api at /graphql using any tool like\ngraphiql you can query this schema like:\n\n```graphql\n   \n   {\n      student\n      {\n        name\n        lastName\n        grades\n      }\n      \n      teacher\n      {\n        name\n        lastName        \n      }\n      \n   }\n\n```\n\nand get as result\n\n```json\n\n   {\n      \"student\": \n      {\n         \"name\": \"Jhon\",\n         \"lastName\": \"Robinson\",\n         \"grades\": 80\n      },\n      \"teacher\":\n      {\n         \"name\": \"Alejandro\",\n         \"lastName\": \"Guardiola\",\n      }\n   }\n\n```\n\n##### Attributes\n\nTo include attributes instead of using a property use a function\n\nRoot.cs\n```csharp\n   \n    public Student Student(string studentId)\n    { \n       return new Student()\n       {\n          Name =\u003e \"Jhon\",\n          LastName =\u003e \"Robinson\",\n          Grades =\u003e 80\n       }       \n    }\n\n```\n\ngraphql:\n```graphql\n    \n    {\n       student(studentId: \"somerandomid\")\n       {\n         name\n       }\n    }\n\n```\n```json\n\n    {\n        \"student\": \n        {\n           \"name\": \"Jhon\"\n        }\n    }    \n\n```\n\n##### Complex Attributes\nTo create custom attribute types, just create the .net class for it\n```csharp\n   \n    public Student Student(SearchCriteria search)\n    { \n       return new Student()\n       {\n          Name =\u003e \"Jhon\",\n          LastName =\u003e \"Robinson\",\n          Grades =\u003e 80\n       }       \n    }\n    \n    // All properties must have both setters\n    public class SearchCriteria\n    {\n        public string Name { get; set; }\n        public string LastName { get; se; }\n    }\n\n```\n```graphql\n    \n    {\n       student(search: { name: \"some name\", lastName: \"some last name\" })\n       {\n         name\n       }\n    }\n\n```\n```json\n\n    {\n        \"student\": \n        {\n           \"name\": \"Jhon\"\n        }\n    }    \n\n```\n##### Lists\n\nEvery type that derive from IEnumerable will be considered as a list,\nfor example we can add a new method in our Root to get all the students\n\nRoot.cs:\n```csharp\n    \n   // this method is inside the Root class\n    public IEnumerable\u003cStudent\u003e AllStudents(int skip, int take)\n    {\n        return new List\u003cStudent\u003e()\n        {\n            new Student()\n            {\n                Name =\u003e \"Jhon\",\n                LastName =\u003e \"Robinson\",\n                Grades =\u003e 80\n            },\n            new Student()\n            {\n                Name =\u003e \"Jhonatan\",\n                LastName =\u003e \"Cruz\",\n                Grades =\u003e 60\n            },\n            new Student()\n            {\n                Name =\u003e \"Rubio\",\n                LastName =\u003e \"Acosta\",\n                Grades =\u003e 30\n            },\n        }.Skip(skip).Take(take);\n    }\n\n```\n```graphql\n    \n    {\n       allStudent(skip: 1, take: 2)\n       {\n         name\n       }\n    }\n\n```\n```json\n\n    {\n        \"allStudent\": [\n           {\n              \"name\": \"Jhonatan\"\n           },\n           {\n              \"name\": \"Rubio\"\n           }\n        ]        \n    }    \n\n```\n\n##### Non null types\nTo mark a type as non null you have to use the [NonNull] attribute,\nwe can put the attribute in anything we want to be non null\nfor example:\n```csharp\n    \n    // this method is inside the Root class\n\n    // the return type has be marked as non null\n    [NonNull]\n                                           // the attributes are marked as non null as well\n    public IEnumerable\u003cStudent\u003e AllStudents([NonNull]int skip, [NonNull]int take)\n    {\n        return new List\u003cStudent\u003e()\n        {\n            new Student()\n            {\n                Name =\u003e \"Jhon\",\n                LastName =\u003e \"Robinson\",\n                Grades =\u003e 80\n            },\n            new Student()\n            {\n                Name =\u003e \"Jhonatan\",\n                LastName =\u003e \"Cruz\",\n                Grades =\u003e 60\n            },\n            new Student()\n            {\n                Name =\u003e \"Rubio\",\n                LastName =\u003e \"Acosta\",\n                Grades =\u003e 30\n            },\n        }.Skip(skip).Take(take);\n    }\n\n```\n\n##### Interfaces\nTo use interfaces you just have to do it as you normally do in .net,\nfor example lets create an interface for Student and Teacher sharing name and lastName:\n\n```csharp\n   \n    public interface IPerson\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }\n    }\n\n    public class Student : IPerson\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }\n        public int Grades { get; set; }\n    }\n\n    public class Teacher : IPerson\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }        \n    }\n\n```\n\nnow we can add a field in the root type to return the interface\n\nRoot.cs\n```csharp\n    \n    // this method is inside the Root class\n    public IPerson Person(string personId)\n    {\n        return Teacher = new Teacher()\n        {\n            Name =\u003e \"Alejandro\",\n            LastName =\u003e \"Guardiola\"\n        }\n    }\n\n```\ngraphql:\n```graphql\n    \n    {\n       person(personId: \"somerandomId\")\n       {\n           name\n           lastName\n           ... on Student\n           {\n              grades\n           }\n       }\n    }\n\n```\n```json\n\n    {\n        \"person\": \n        {\n           \"name\": \"Alejandro\",\n           \"lastName\": \"Guardiola\"\n        }        \n    }    \n\n```\n\n##### Unions\nFor union types use the Union\u003c\u003e class or derive from it,\nfor example if we want to create an union of string and int\nwe return Union\u003cstring, int\u003e or create a class that derive from it.\n\nRoot.cs\n```csharp\n    \n    // this property is inside the Root class\n    public Union\u003cstring, int\u003e UnionTest =\u003e new Union\u003cstring, int\u003e(\"My value\");    \n    // this property is inside the Root class\n    public Union\u003cstring, int\u003e UnionTest2 =\u003e new Union\u003cstring, int\u003e(10);\n\n```\n\ngraphql:\n```graphql\n    \n    {\n       unionTest\n       unionTest2\n    }\n\n```\n```json\n\n    {\n        \"unionTest\": \"My value\",\n        \"unionTest2\": 10              \n    }    \n\n```\n\n##### Mutations\n\nTo create mutations just create a class or multiple classes\nwith the mutations but it should derive from GraphNodeType and have the mutation attribute \nwith the Root type that they are mutating\n\n```csharp\n   \n   // must have this attribute with the type of the root that they mutate\n   [Mutation(tyepof(Root))]\n   public class StudentMutations : GraphNodeType\n   {\n      // inside the class we create the functions for the mutations\n      public Student AddStudent([NonNull]StudentInput student)\n      {\n          // logic to add student to the database\n          return new Student()\n          {\n             Name = student.Name,\n             LastName = student.LastName,\n             Grades = student.Grades\n          }\n      }\n   }\n   \n   public class StudentInput\n   {\n      [NonNull]\n      public string Name { get; set; }\n      [NonNull]\n      public string LastName { get; set; }\n      [NonNull]\n      public int Grades { get; set; }\n   }\n\n```\n\ngraphql:\n```graphql\n    \n    mutation {\n       addStudent(student:{\n          name: \"Alejandro\",\n          lastName: \"Guardiola\",\n          grades: 0\n       })\n       {\n          name\n       }\n    }\n\n```\n```json\n\n    {\n        \"addStudent\": \n        {\n            \"name\": \"Alejandro\"\n        }\n    }    \n\n```\n\n\n##### Subscriptions\n\nSimilar to mutations to create subscriptions a class or multiple classes\ncontaining the subscriptions have to have GraphNodeType as base class and\nthey have to use the SubscriptionAttribute with the type of the root that \nthe subscriptions belog to. Every subscription have to retirn an IObservable.\n\n```csharp\n   \n   // must have this attribute with the type of the root that \n   // the subscriptions belog to.\n   [Subscription(tyepof(Root))]\n   public class StudentSubscriptions : GraphNodeType\n   {\n      // return the observable to the subscription\n      // in this example we are just using an array of students\n      // and streamming a value every 2 seconds.\n      public IObservable\u003cTeacher\u003e TeacherAdded() =\u003e new IPerson[] {\n\n            new Teacher()\n            {\n                Name = \"Alejo\",\n                LastName = \"Guardiola\",\n            },\n            new Teacher()\n            {\n                Name = \"AlejoA\",\n                LastName = \"GuardiolaA\",\n            },\n            new Teacher()\n            {\n                Name = \"AlejoB\",\n                LastName = \"GuardiolaB\",\n            },\n            new Teacher()\n            {\n                Name = \"AlejoC\",\n                LastName = \"GuardiolaC\",\n            },\n            new Teacher()\n            {\n                Name = \"AlejoD\",\n                LastName = \"GuardiolaD\",\n            }\n\n        }.ToObservable().Zip(Observable.Interval(TimeSpan.FromSeconds(2)), (x, y) =\u003e x);\n      \n   }   \n\n```\n\ngraphql:\n```graphql\n    \n    subscription {\n       teacherAdded\n       {\n          name\n       }\n    }\n\n```\n\nTo use it in asp.net core in the Configure method in your Startup.cs\nadd:\n```csharp\n  app.UseWebSockets();\n  ...\n  // after UseGraphQLController()\n  app.UseGraphqlWebSocketProtocol\u003cRoot\u003e(\"/graphql\");\n```\n\nThis implementation uses apollo websocket subscription protocol, \nyou can use apollo client learn more here: \nhttps://www.apollographql.com/docs/react/data/subscriptions/\n\nSignalR support is comming!!\n\n#### Type description\n\nThre is two ways to create a description for a type\n\n##### Using the Description Attribute\n\nPutting the description attribute where we want the description\n\n```csharp\n   \n    [Description(\"Represent a person\")]\n    public interface IPerson\n    {\n        [Description(\"Person name.\")]\n        public string Name { get; set; }\n        [Description(\"Person last name.\")]\n        public string LastName { get; set; }\n    }\n    \n    [Description(\"Represent an student\")]\n    public class Student : IPerson\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }\n        public int Grades { get; set; }\n    }\n\n```\n\nthe attribute can be used for the fields attributes as well\n\n##### Using the C# xml documentation\n\nJust creating a xml documentation for the property or method where we want the description\n\n```csharp\n   \n   [Mutation(typeof(Root))]\n    public class StudentMutations : GraphNodeType\n    {\n        /// \u003csummary\u003e\n        /// Add a new student to the database\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"student\"\u003eThe student to add\u003c/param\u003e\n        /// \u003creturns\u003e\u003c/returns\u003e\n        public Student AddStudent([NonNull]StudentInput student)\n        {\n            \n            return new Student()\n            {\n                Name = student.Name,\n                LastName = student.LastName,\n                Grades = student.Grades\n            };\n        }\n    }\n\n    public class StudentInput\n    {\n        /// \u003csummary\u003e\n        /// Name of the student\n        /// \u003c/summary\u003e\n        [NonNull]\n        public string Name { get; set; }\n\n        /// \u003csummary\u003e\n        /// Last name of the student\n        /// \u003c/summary\u003e\n        [NonNull]\n        public string LastName { get; set; }\n\n        /// \u003csummary\u003e\n        /// Grades\n        /// \u003c/summary\u003e\n        [NonNull]\n        public int Grades { get; set; }\n    }\n\n```\n\nThe only downside of this method is that for this to work you have to include the\nxml documentation file in the build\n\n#### Custom type name\nTo asignate a custom name to the type, the type must have the Name attribute\n\n```csharp\n    \n    [Name(\"MyCustomStudentTypeName\")]\n    public class Student : IPerson\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }\n        public int Grades { get; set; }\n    }\n\n```\n\nthis can be used for the attributes as well\n\n#### Async - Await\nWhen  you return a Task\u003c\u003e from a field GraphQLController automatically\ntake of that.\n\nYou can get the CancellationToken by adding it in the method parameters\n\n```csharp\n    public async Task\u003cStudent\u003e AddStudent(StudentInput student, CancellationToken cancellationToken)\n    {\n       return await // some result      \n    }\n```\n\n#### Dependency Injection\nGraphqlController support Dependency Injection out of the box, it integrates \nwith the built-in asp.net core dependency injection.\nTo inject services to a type it must derive from GraphNodeType, because the root\n and the mutations types already has to derive from it, you can inject services in the root and mutations\nalready.\n\nRoot.cs:\n```csharp\n    \n   [RootType]\n   public class Root : GraphNodeType\n   {\n        // private methods and properties are ignored\n        private StudentRepository _studentRepo;\n\n        public Root(StudentRepository studentRepo)\n        {\n            _studentRepo = studentRepo;\n        }\n        \n        // exposed by the graphql api\n        public List\u003cStudent\u003e AllStudents =\u003e _studentRepo.GetAll();\n   }\n\n```\n\n#### Dependency Injection in nested types\nIn order to use dependency injection in nested types, again they have\nto derive from GraphNodeType and be created using IGraphqlResolver service.\nClasses that derive from GraphNodeType can override the OnCreateAsync function\nto initialize\n\nLets modify the Teacher class a little:\n\n```csharp\n\n      // TeacherDomain in the genric parameter\n      // is a custom parameter that we can pass to the instance\n      // to initialized\n      public class Teacher : GraphNodeType\u003cTeacherDomain\u003e\n      {        \n        StudentRepo _studentRepo;\n\n        // Inject services\n        public Teacher(StudentRepo studentRepo)\n        {\n            _studentRepo = studentRepo;\n        }        \n        \n        public override Task OnCreateAsync(TeacherDomain domain, CancellationToken cancellationToken)\n        {\n            // Initialize the instance here\n            Name = domain.Name;\n            LastName = domain.LastName;\n            return Task.CompletedTask;\n        }\n\n        public string Name { get; set; }\n        public string LastName { get; set; }    \n\n        public IEnumerable\u003cStudent\u003e Students()\n        {\n            return _studentRepo.GetTeacherStudents(Name);\n        }  \n        \n    \n      }\n```\n\nNow to create the teacher from another type we use the IGraphqlResolver service:\n\nRoot.cs\n```csharp\n    \n    // services injected in Root\n    IGraphqlResolver _graphqlResolver;\n    TeacherRepo _teacherRepo;\n\n    // this method is inside Root.cs\n    public async Task\u003cTeacher\u003e Teacher(string name, CancellationToken cancellationToken)\n    {\n        var teacherDomain = _techerRepo.GetTeacherByName(name);\n        // create teacher using IGraphqlResolver\n        return await _graphqlResolver.CreateGraphqlEnityAsync\u003cTeacher, TeacherDomain\u003e(teacherDomain, cancellationToken);\n    }\n\n```\n\n## Persisted Queries\nA persisted query is an ID or hash that can be sent to the server instead of the entire GraphQL query string. This smaller signature reduces bandwidth utilization and speeds up client loading times. Persisted queries are especially nice paired with GET requests, enabling the browser cache and integration with a CDN.\n(Copied from the Apollo documentation)\n\nPersisted queries are implmented using the Apollo protocol\nhttps://github.com/apollographql/apollo-link-persisted-queries#protocol\n\n#### How to enable Persisted Queries\n\nPersisted queries can be cached using memory cache or a distributed cache.\n\n##### Persisted queries using Memory Cache\nUsing memory cache the queries are stored on the app memory. This aproach works \nwell for the majority of many cases:\n\nPros:\n   * It is fast because works with the app memory\n   * Dont need an external service or store\n   * Dont need any configuration\n\nCons:\n   * Cannot be share between multiple app instances\n   * The cache is reseted every time the app restart\n   * Many queries cached can make your memory go higher\n\nTo enable Persisted queries with memory cache call, you have to make sure \nyou have Asp.net core memory cache added to your services you can learn more here:\nhttps://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1\n\nIn your Startup.cs in ConfigureServices add:\n```csharp\n\n    // add asp.net core memory cache\n    services.AddMemoryCache();\n\n    services.AddGraphQlEndpoint()\n    // add in memory persisted query support\n            .AddPersistedQuery()\n            .AddInMemoryPersistedQuery();\n\n```\n\nIn your Startup.cs in Configure add:\n```csharp\n\n   app.UseGraphQLController()\n          // specify for what root you want the middleware\n          .UseGraphQlExecutionFor\u003cRoot\u003e()\n          // add persisted query execution middleware\n                .UsePersistedQuery(); \n\n```\n\n##### Persisted queries using Distributed Cache\n(From Microsoft docs)\nA distributed cache is a cache shared by multiple app servers, typically maintained as an external service to the app servers that access it. A distributed cache can improve the performance and scalability of an ASP.NET Core app, especially when the app is hosted by a cloud service or a server farm.\n\nA distributed cache has several advantages over other caching scenarios where cached data is stored on individual app servers.\n\nPros:\n  * Is coherent (consistent) across requests to multiple servers.\n  * Survives server restarts and app deployments.\n  * Doesn't use local memory.\n\nCons:\n  * Require external cache service (Redis, NCache, etc...)\n  * Require more configuration\n  * Slighty slower than Memory Cache\n\nTo use it first add the distributed cache: \nhttps://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-3.1\n\nand then call AddDistributedPersistedQuery in your services.\n\nIn your Startup.cs in ConfigureServices add:\n```csharp\n\n    // add asp.net core memory cache\n    services.AddMemoryCache();\n\n    services.AddGraphQlEndpoint()\n    // add distributed persisted query support\n            .AddDistributedPersistedQuery();\n```\n\nand dont forget to add the middleware as explained in In Memory Persisted queries\n\n## Cache\n\nYou can cache resources that does not change frequently, this is very useful because\nthe server does not need to recompute the values or get it from the database\nevery time a client request it.\n\nGraphqlController.AspNetCore has support for caching with the CacheControlAttribute. \nYou can use CacheControlAttribute on a Type or a field to indicate the time in seconds\nthat the specific resource will be cached.\n\n```csharp\n\n    // Student will be cached for 60 seconds\n    [CacheControl(60)]\n    public class Student : IPerson\n    {\n        public string Name { get; set; }\n        public string LastName { get; set; }\n        public int Grades { get; set; }\n    }\n    \n```\n\n```csharp\n\n    // The field allStudents will be cached for 10 seconds.\n    // When you use it on a field it will override any Cache that the\n    // type has, this means that the 60 seconds on the type Student\n    // will be overrided to 10\n    [CacheControl(10)]\n    public IEnumerable\u003cStudent\u003e AllStudents([NonNull]int skip, [NonNull]int take)\n    {\n        return new List\u003cStudent\u003e()\n        {\n            new Student()\n            {\n                Name =\u003e \"Jhon\",\n                LastName =\u003e \"Robinson\",\n                Grades =\u003e 80\n            },\n            new Student()\n            {\n                Name =\u003e \"Jhonatan\",\n                LastName =\u003e \"Cruz\",\n                Grades =\u003e 60\n            },\n            new Student()\n            {\n                Name =\u003e \"Rubio\",\n                LastName =\u003e \"Acosta\",\n                Grades =\u003e 30\n            },\n        }.Skip(skip).Take(take);\n    }\n\n```\n\nAfter the query is executed the cache time in second will be computed for\nthat execution. The current cache policy takes the lowest value.\n\nFor the cache to work we have to added in our services\n\nIn your Startup.cs in ConfigureServices add:\n```csharp\n\n    services.AddGraphQlEndpoint()            \n            .AddGraphqlCache(new CacheConfiguration()\n            {\n                // Default max age in seconds if no cache control\n                // can be found the default value is 0\n                DefaultMaxAge = 5,\n                // Set this option if you want to cache the responses\n                // using the server cache, the options are Distributed,\n                // Memory or None by default. If you want to use other different\n                // than none make sure you have the correspondent cache service\n                // as explained in persisted queries.\n                ResponseCache = ResponseCacheType.Distributed,\n                // When this property is set to true the cache control\n                // headers will be included if the request is served\n                // via HTTP GET. This is very useful because browsers\n                // can cache the responses and not even have to ask \n                // the server. If you use the Apollo Client this is a \n                // good combination with persisted queries forced to GEET\n                // only. The default value is false.\n                UseHttpCaching = true,\n                // When this property is set to true the eEtag header\n                // will be computed in the response, this is ver useful\n                // if you want to save bandwidth. The browser will include\n                // the hash and if the hash is equal to the response hash\n                // the server will send a status code of 304(Not Modified).\n                // Only for GET requests\n                IncludeETag = true\n            });\n```\n\n\nIn your Startup.cs in Configure add:\n```csharp\n\n   app.UseGraphQLController()\n          // specify for what root you want the middleware\n          .UseGraphQlExecutionFor\u003cRoot\u003e()\n          // Important!! This middleware must be the last one registerd\n          // That means if you register another middleware like\n          // .UsePersistedQuery() this one must go after.\n                .UseCache();\n\n```\n\n\n##### Comming features\n* Support for the graphql net server project\n* Posibly more features to add and bugs to fix\n\n\n#### Special Thanks\n* This library is not possible without https://github.com/graphql-dotnet/graphql-dotnet\n\n* And also to make the xml documentation descriptions https://github.com/loxsmoke/DocXml\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDevelop-Genesis%2FGraphql-Controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDevelop-Genesis%2FGraphql-Controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDevelop-Genesis%2FGraphql-Controller/lists"}