{"id":27165,"date":"2020-03-25T00:00:00","date_gmt":"2020-03-24T23:00:00","guid":{"rendered":"https:\/\/blexin.com\/?p=27165"},"modified":"2021-01-13T09:40:09","modified_gmt":"2021-01-13T08:40:09","slug":"creiamo-la-nostra-api-con-graphql-e-hot-chocolate","status":"publish","type":"post","link":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/","title":{"rendered":"Creiamo la nostra API con GraphQL e Hot Chocolate"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" data-attachment-id=\"27128\" data-permalink=\"https:\/\/blexin.com\/it\/top00-3\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&amp;ssl=1\" data-orig-size=\"1024,608\" data-comments-opened=\"0\" data-image-title=\"top00-3\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?resize=1024%2C608&#038;ssl=1\" alt=\"\" class=\"wp-image-27128\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3-980x582.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3-480x285.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Quante volte vi \u00e8 capitato di chiamare una API e ricevere pi\u00f9 dati di quelli che vi servivano?&nbsp;Oppure, nel caso opposto, di riceverne di meno e di dover quindi fare pi\u00f9 chiamate ad endpoint diversi per avere tutte le informazioni necessarie?<br>Questi due fenomeni prendono il nome rispettivamente di&nbsp;<strong>overfetching&nbsp;<\/strong>e&nbsp;<strong>underfetching,&nbsp;<\/strong>e probabilmente rappresentano il pi\u00f9 grosso problema dell\u2019uso di una API REST.<br>Serviva qualcosa che avesse una flessibilit\u00e0 maggiore, in cui il client, con una specifica query, fosse in grado di recuperare tutte le informazioni necessarie e soltanto quelle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con GraphQL, tutto questo si pu\u00f2 fare.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">GraphQL agisce come un middle layer tra la nostre fonte di dati e i nostri client. Pu\u00f2 essere considerato come un\u2019alternativa alle REST API, se non una loro evoluzione.<br>\u00c8 un query language: ci\u00f2 significa che, rispetto ad altre architetture di interfaccia che accettano solo query molto rigorose e spesso indirizzate su una singola risorsa, le query GraphQL, sono caratterizzate da un elevato grado di flessibilit\u00e0. Il Client richiede esattamente i campi che gli interessano.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Questa flessibilit\u00e0 la ritroviamo anche in fase di ampliamenti dell\u2019API: infatti, l\u2019aggiunta di campi restituiti alla nostra struttura non andr\u00e0 ad impattare sui client esistenti.<br>La forte tipizzazione \u00e8 un\u2019altra caratteristica di GraphQL: ogni livello di query corrisponde ad un determinato tipo, e ogni tipo descrive un set di campi disponibili. Questo permette a GraphQL di effettuare una validazione della query prima di eseguirla, restituendo anche messaggi di errore descrittivi.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ci sono quattro concetti chiave in GraphQL:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Schema<\/li><li>Resolver<\/li><li>Query<\/li><li>Mutation<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Uno&nbsp;<strong>schema<\/strong>&nbsp;GraphQL \u00e8 composto da tipi di oggetto che definiscono la tipologia di oggetti che \u00e8 possibile richiedere e i tipi di campi disponibili al suo interno.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&nbsp;<strong>resolver<\/strong>&nbsp;sono i collaboratori che possiamo associare ai campi del nostro schema e che si occuperanno di recuperare i dati di tali campi.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Considerando una tipica CRUD di un dato, possiamo andare a definire il concetto di&nbsp;<strong>query<\/strong>&nbsp;e&nbsp;<strong>mutation<\/strong>. La prima si occuper\u00e0 della lettura dell\u2019informazione, mentre la creazione, modifica e cancellazione sono mansioni prese in carico dalle mutation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Proviamo ora a creare un\u2019applicazione in grado di eseguire una CRUD con GraphQL.<br>Lo facciamo in ASP.NET Core con Hot Chocolate, una libreria che permette di creare un implementazione server di GraphQL.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Creiamo un progetto ASP.NET Core Web, e aggiungiamo mediante pacchetti Nuget la libreria HotChocolate e HotChocolate.AspNetCore. Si \u00e8 dimostrata molto utile anche la libreria HotChocolate.AspNetCore.Playground, che permette di testare nel browser l\u2019API che stiamo sviluppando.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Al file di Startup.cs andiamo ad aggiungere le istruzioni necessarie per configurare GraphQL.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nnamespace DemoGraphQL\n{\n    public class Startup\n    {\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.AddGraphQL(s =&gt; SchemaBuilder.New()\n                .AddServices(s)\n                .AddType&lt;AuthorType&gt;()\n                .AddType&lt;BookType&gt;()\n                .AddQueryType&lt;Query&gt;()\n                .Create());\n        }\n \n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            if (env.IsDevelopment())\n            {\n                app.UsePlayground();\n            }\n \n            app.UseGraphQL(&quot;\/api&quot;);\n        }\n    }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Definiamo&nbsp;<strong>AuthorType<\/strong>&nbsp;e&nbsp;<strong>BookType<\/strong>, che saranno i tipi esposti dalla nostra Api.<br>In queste due classi andiamo ad indicare quali campi delle classi di dominio&nbsp;<strong>Author<\/strong>&nbsp;e&nbsp;<strong>Book<\/strong>&nbsp;verranno esposti.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class AuthorType : ObjectType&lt;Author&gt;\n{\n\u00a0\u00a0\u00a0\u00a0protected override void Configure(IObjectTypeDescriptor&lt;Author&gt; descriptor)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(a =&gt; a.Id).Type&lt;IdType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(a =&gt; a.Name).Type&lt;StringType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(a =&gt; a.Surname).Type&lt;StringType&gt;();\n\u00a0\u00a0\u00a0\u00a0}\n}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\npublic class Author\n{\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\u00a0\u00a0\u00a0public string Name { get; set; }\n\u00a0\u00a0\u00a0\u00a0public string Surname { get; set; }\n}\n\u00a0\npublic class BookType : ObjectType&lt;Book&gt;\n{\n\u00a0\u00a0\u00a0\u00a0protected override void Configure(IObjectTypeDescriptor&lt;Book&gt; descriptor)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(b =&gt; b.Id).Type&lt;IdType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(b =&gt; b.Title).Type&lt;StringType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(b =&gt; b.Price).Type&lt;DecimalType&gt;();\n\u00a0\u00a0\u00a0\u00a0}\n}\n\u00a0\u00a0\n\u00a0\npublic class Book\n{\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\u00a0\u00a0\u00a0public string Title { get; set; }\n\u00a0\u00a0\u00a0\u00a0public decimal Price { get; set; }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">A questo punto, possiamo creare la classe Query, iniziando con il definire gli autori.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class Query\n{\n\u00a0\u00a0\u00a0\u00a0private readonly IAuthorService _authorService;\n\u00a0\u00a0\u00a0\u00a0public Query(IAuthorService authorService)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_authorService = authorService;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0&#x5B;UsePaging(SchemaType = typeof(AuthorType))]\n\u00a0\u00a0\u00a0\u00a0public IQueryable&lt;Author&gt; Authors =&gt; _authorService.GetAll();\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Con l\u2019annotazione UsePaging, stiamo istruendo GraphQL in modo tale che gli autori restituiti dall\u2019apposito service dovranno essere resi disponibili in forma paginata e nel tipo&nbsp;<strong>AuthorType<\/strong>&nbsp;definito in precedenza.<br>In questo modo, avviando l\u2019applicazione e andando nel playground, possiamo effettuare la seguente query e vedere il risultato.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-5.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27133\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-5.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-5-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Aggiungendo la libreria HotChocolate.Types e HotChocolate.Types.Filters \u00e8 possibile aggiungere una nuova annotation per abilitare i filtri.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;UsePaging(SchemaType = typeof(AuthorType))]\n&#x5B;UseFiltering]\npublic IQueryable&lt;Author&gt; Authors =&gt; _authorService.GetAll();\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27138\" data-permalink=\"https:\/\/blexin.com\/it\/image02-4\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-4.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image02-4\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-4.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-4.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27138\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-4.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-4-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Anche con la query sui libri otteniamo lo stesso risultato<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;UsePaging(SchemaType = typeof(BookType))]\n&#x5B;UseFiltering]\npublic IQueryable&lt;Book&gt; Books =&gt; _bookService.GetAll();\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27141\" data-permalink=\"https:\/\/blexin.com\/it\/image03-3\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-3.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image03-3\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-3.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-3.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27141\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-3.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-3-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In questo momento, libri e autori non sono legati tra loro, ma in un\u2019applicazione reale vogliamo poter ottenere le informazioni degli autori quando facciamo una query sui libri e allo stesso modo vogliamo ottenere la lista dei libri scritti quando facciamo una query sugli autori.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Modifichiamo la classe&nbsp;<strong>Book<\/strong>&nbsp;per aggiungere l\u2019id autore:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class Book\n{\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\u00a0\u00a0\u00a0public int AuthorId { get; set; }\n\u00a0\u00a0\u00a0\u00a0public string Title { get; set; }\n\u00a0\u00a0\u00a0\u00a0public decimal Price { get; set; }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">A questo punto, possiamo utilizzare uno degli elementi elencati prima di GraphQL: i resolver. Implementiamo per primo quello che ci permette di ottenere informazioni dell\u2019autore sulla query dei libri.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class BookType : ObjectType&lt;Book&gt;\n{\n\u00a0\u00a0\u00a0\u00a0protected override void Configure(IObjectTypeDescriptor&lt;Book&gt; descriptor)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(b =&gt; b.Id).Type&lt;IdType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(b =&gt; b.Title).Type&lt;StringType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(b =&gt; b.Price).Type&lt;DecimalType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field&lt;AuthorResolver&gt;(t =&gt; t.GetAuthor(default, default));\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Abbiamo aggiunto un nuovo campo allo schema&nbsp;<strong>BookType<\/strong>&nbsp;con&nbsp;<em>descriptor.Field<\/em>&nbsp;e gli abbiamo detto di risolverlo mediante il metodo&nbsp;<strong>GetAuthor<\/strong>&nbsp;di&nbsp;<strong>AuthorResolver<\/strong>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class AuthorResolver\n{\n\u00a0\u00a0\u00a0\u00a0private readonly IAuthorService _authorService;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public AuthorResolver(&#x5B;Service]IAuthorService authorService)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_authorService = authorService;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public Author GetAuthor(Book book, IResolverContext ctx)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return _authorService.GetAll().Where(a =&gt; a.Id == book.AuthorId).FirstOrDefault();\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27144\" data-permalink=\"https:\/\/blexin.com\/it\/image04-4\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-4.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image04-4\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-4.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-4.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27144\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-4.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-4-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Allo stesso modo, possiamo definire un nuovo campo con rispettivo resolver per aggiungere agli autori anche i libri che hanno scritto.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class AuthorType : ObjectType&lt;Author&gt;\n{\n\u00a0\u00a0\u00a0\u00a0protected override void Configure(IObjectTypeDescriptor&lt;Author&gt; descriptor)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(a =&gt; a.Id).Type&lt;IdType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(a =&gt; a.Name).Type&lt;StringType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field(a =&gt; a.Surname).Type&lt;StringType&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0descriptor.Field&lt;BookResolver&gt;(t =&gt; t.GetBooks(default, default));\n\u00a0\u00a0\u00a0\u00a0}\n}\n\u00a0\n\u00a0\npublic class BookResolver\n{\n\u00a0\u00a0\u00a0\u00a0private readonly IBookService _bookService;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public BookResolver(&#x5B;Service]IBookService bookService)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_bookService = bookService;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0public IEnumerable&lt;Book&gt; GetBooks(Author author, IResolverContext ctx)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return _bookService.GetAll().Where(b =&gt; b.AuthorId == author.Id);\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27147\" data-permalink=\"https:\/\/blexin.com\/it\/image05-5\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-5.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image05-5\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-5.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-5.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27147\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-5.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-5-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Per completare la CRUD con le operazioni di creazione e cancellazione, dobbiamo implementare quella che viene definita&nbsp;<strong>mutation.<\/strong>&nbsp;Non \u00e8 altro che una classe con metodi che indicano le operazioni possibili.<br>Deve essere registrata mediante la seguente istruzione&nbsp;<code>AddMutationType&lt;Mutation&gt;()<\/code>&nbsp;che va aggiunta al blocco di configurazione di GraphQL nello Startup.cs<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nservices.AddGraphQL(s =&gt; SchemaBuilder.New()\n\u00a0\u00a0\u00a0\u00a0.AddServices(s)\n\u00a0\u00a0\u00a0\u00a0.AddType&lt;AuthorType&gt;()\n\u00a0\u00a0\u00a0\u00a0.AddType&lt;BookType&gt;()\n\u00a0\u00a0\u00a0\u00a0.AddQueryType&lt;Query&gt;()\n\u00a0\u00a0\u00a0\u00a0.AddMutationType&lt;Mutation&gt;()\n\u00a0\u00a0\u00a0\u00a0.Create());\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Iniziamo aggiungendo un metodo che ci permetta di inserire un nuovo libro:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class Mutation\n{\n\u00a0\u00a0\u00a0\u00a0private readonly IBookService _bookService;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public Mutation(IBookService bookService)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_bookService = bookService;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public Book CreateBook(CreateBookInput inputBook)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return _bookService.Create(inputBook);\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">creiamo anche la classe di input che dovremo inserire nella query<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic class CreateBookInput\n{\n\u00a0\u00a0\u00a0\u00a0public string Title { get; set; }\n\u00a0\u00a0\u00a0\u00a0public decimal Price { get; set; }\n\u00a0\u00a0\u00a0\u00a0public int AuthorId { get; set; }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Il service non dovr\u00e0 fare altro che creare una nuova istanza di Book, aggiungerla alla sua lista e restituire il libro creato.<br>Dal playground, possiamo testare la nuova funzionalit\u00e0 passando la query come da shot.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27150\" data-permalink=\"https:\/\/blexin.com\/it\/image06-4\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-4.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image06-4\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-4.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-4.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27150\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-4.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-4-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Aggiungiamo ora la funzionalit\u00e0 di rimozione di un libro.<br>Cos\u00ec come per la creazione, occorre aggiungere un metodo alla mutation.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic Book DeleteBook(DeleteBookInput inputBook)\n{\n\u00a0\u00a0\u00a0\u00a0return _bookService.Delete(inputBook);\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">La classe&nbsp;<strong>DeleteBookInput<\/strong>&nbsp;contiene solo una property di tipo int che rappresenta l\u2019Id del libro che si vuole eliminare.<br>Una possibile implementazione del metodo&nbsp;<strong>Delete<\/strong>&nbsp;del Service \u00e8 la seguente :<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic Book Delete(DeleteBookInput inputBook)\n{\n\u00a0\u00a0\u00a0\u00a0var bookToDelete = _books.Single(b =&gt; b.Id == inputBook.Id);\n\u00a0\u00a0\u00a0\u00a0_books.Remove(bookToDelete);\n\u00a0\u00a0\u00a0\u00a0return bookToDelete;\n}\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27156\" data-permalink=\"https:\/\/blexin.com\/it\/image07-4\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image07-4.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image07-4\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image07-4.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image07-4.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27156\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image07-4.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image07-4-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Provando a rieseguire la query, otterremo un messaggio di errore relativo all\u2019eccezione lanciata dal metodo Single. Possiamo rendere il messaggio di errore pi\u00f9 descrittivo, cos\u00ec da non generare dubbi in chi chiama la nostra API.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27158\" data-permalink=\"https:\/\/blexin.com\/it\/image08-3\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image08-3.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image08-3\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image08-3.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image08-3.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27158\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image08-3.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image08-3-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Creamo una nuova Exception<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class BookNotFoundException : Exception\n{\n\u00a0\u00a0\u00a0\u00a0public int BookId { get; internal set; }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">E facciamo in modo che venga lanciata questa, nel caso in cui non sia stato possibile trovare il libro da cancellare.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic Book Delete(DeleteBookInput inputBook)\n{\n\u00a0\u00a0\u00a0\u00a0var bookToDelete = _books.FirstOrDefault(b =&gt; b.Id == inputBook.Id);\n\u00a0\u00a0\u00a0\u00a0if (bookToDelete == null)\n\u00a0\u00a0\u00a0\u00a0throw new BookNotFoundException() { BookId = inputBook.Id };\n\u00a0\u00a0\u00a0\u00a0_books.Remove(bookToDelete);\n\u00a0\u00a0\u00a0\u00a0return bookToDelete;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Ora creiamo una classe che implementa&nbsp;<strong>IErrorFilter<\/strong>&nbsp;messo a disposizione da HotChocolate che intercetta&nbsp;<strong>BookNotFoundException<\/strong>&nbsp;e aggiunge all\u2019errore le informazioni che vogliamo restituire all\u2019utente.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic class BookNotFoundExceptionFilter : IErrorFilter\n{\n\u00a0\u00a0\u00a0\u00a0public IError OnError(IError error)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (error.Exception is BookNotFoundException ex)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return error.WithMessage($&quot;Book with id {ex.BookId} not found&quot;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return error;\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Infine, andiamo a registrare questa classe nello Startup<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nservices.AddErrorFilter&lt;BookNotFoundExceptionFilter&gt;();\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"657\" data-attachment-id=\"27162\" data-permalink=\"https:\/\/blexin.com\/it\/image09-2-3\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image09-2.png?fit=981%2C657&amp;ssl=1\" data-orig-size=\"981,657\" data-comments-opened=\"0\" data-image-title=\"image09-2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image09-2.png?fit=981%2C657&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image09-2.png?resize=981%2C657&#038;ssl=1\" alt=\"\" class=\"wp-image-27162\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image09-2.png 981w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image09-2-480x321.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 981px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">La nostra API \u00e8 finalmente completa, il codice come sempre \u00e8 sul mio github&nbsp;<a href=\"https:\/\/github.com\/AARNOLD87\/GraphQLWithHotChocolate\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/AARNOLD87\/GraphQLWithHotChocolate<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Al termine del progetto ho pensato: sembra tutto fantastico, perch\u00e9 non ho utilizzato GraphQL per tutte le API? C\u2019\u00e8 qualche svantaggio che non ho considerato?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In questa demo, abbiamo implementato la gestione degli errori. In API REST, quando qualcosa non va a buon fine, ci aspettiamo uno Status Code diverso da 200. In GraphQL, invece, otterremo sempre 200, anche in caso di errore. Questo vuol dire che il client dovr\u00e0 basarsi esclusivamente sul contenuto della risposta, senza poter prendere decisioni preventive in base allo stato ricevuto dalla richiesta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Altro aspetto che in una demo ovviamente non viene fuori, \u00e8 il discorso legato al&nbsp;<strong>caching<\/strong>.<br>Non c\u2019\u00e8 un supporto di cache built-in e implementarlo non \u00e8 cos\u00ec semplice come accade con le API REST. Un aspetto da non sottovalutare.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Spero di avervi incuriosito.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Al prossimo articolo!<\/p>\n\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>GraphQL: vediamo cos\u2019\u00e8, cosa ci permette di fare e come \u00e8 possibile creare una API in ASP.NET Core con Hot Chocolate<\/p>\n","protected":false},"author":196716250,"featured_media":27129,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"","_et_gb_content_width":"","_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_wpcom_ai_launchpad_first_post":false,"_jetpack_hide_featured_image":false,"_jetpack_featured_image_duplicate_dismissed":0,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"{title}\n\n{excerpt}\n\n{url}","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[688637374],"tags":[688637414,688637382,688637415],"class_list":["post-27165","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-asp-net-core","tag-c","tag-graphql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Creiamo la nostra API con GraphQL e Hot Chocolate - Blexin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creiamo la nostra API con GraphQL e Hot Chocolate - Blexin\" \/>\n<meta property=\"og:description\" content=\"GraphQL: vediamo cos\u2019\u00e8, cosa ci permette di fare e come \u00e8 possibile creare una API in ASP.NET Core con Hot Chocolate\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/\" \/>\n<meta property=\"og:site_name\" content=\"Blexin\" \/>\n<meta property=\"article:published_time\" content=\"2020-03-24T23:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-13T08:40:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"608\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Adolfo Arnold\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Adolfo Arnold\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/\"},\"author\":{\"name\":\"Adolfo Arnold\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/0de430b61c8a48b0e9d81308817c1517\"},\"headline\":\"Creiamo la nostra API con GraphQL e Hot Chocolate\",\"datePublished\":\"2020-03-24T23:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/\"},\"wordCount\":1136,\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/top00-3.png?fit=1024%2C608&ssl=1\",\"keywords\":[\"Asp.net core\",\"C#\",\"GraphQL\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/\",\"name\":\"Creiamo la nostra API con GraphQL e Hot Chocolate - Blexin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/top00-3.png?fit=1024%2C608&ssl=1\",\"datePublished\":\"2020-03-24T23:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:09+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/0de430b61c8a48b0e9d81308817c1517\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/top00-3.png?fit=1024%2C608&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/top00-3.png?fit=1024%2C608&ssl=1\",\"width\":1024,\"height\":608},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blexin.com\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Creiamo la nostra API con GraphQL e Hot Chocolate\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/\",\"name\":\"Blexin\",\"description\":\"Con noi \u00e8 semplice\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blexin.com\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/0de430b61c8a48b0e9d81308817c1517\",\"name\":\"Adolfo Arnold\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g\",\"caption\":\"Adolfo Arnold\"},\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/author\\\/adolfo-arnoldblexin-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Creiamo la nostra API con GraphQL e Hot Chocolate - Blexin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/","og_locale":"it_IT","og_type":"article","og_title":"Creiamo la nostra API con GraphQL e Hot Chocolate - Blexin","og_description":"GraphQL: vediamo cos\u2019\u00e8, cosa ci permette di fare e come \u00e8 possibile creare una API in ASP.NET Core con Hot Chocolate","og_url":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/","og_site_name":"Blexin","article_published_time":"2020-03-24T23:00:00+00:00","article_modified_time":"2021-01-13T08:40:09+00:00","og_image":[{"width":1024,"height":608,"url":"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&ssl=1","type":"image\/png"}],"author":"Adolfo Arnold","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Adolfo Arnold","Tempo di lettura stimato":"8 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/#article","isPartOf":{"@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/"},"author":{"name":"Adolfo Arnold","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/0de430b61c8a48b0e9d81308817c1517"},"headline":"Creiamo la nostra API con GraphQL e Hot Chocolate","datePublished":"2020-03-24T23:00:00+00:00","dateModified":"2021-01-13T08:40:09+00:00","mainEntityOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/"},"wordCount":1136,"image":{"@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&ssl=1","keywords":["Asp.net core","C#","GraphQL"],"articleSection":["Blog"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/","url":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/","name":"Creiamo la nostra API con GraphQL e Hot Chocolate - Blexin","isPartOf":{"@id":"https:\/\/blexin.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/#primaryimage"},"image":{"@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&ssl=1","datePublished":"2020-03-24T23:00:00+00:00","dateModified":"2021-01-13T08:40:09+00:00","author":{"@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/0de430b61c8a48b0e9d81308817c1517"},"breadcrumb":{"@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/#primaryimage","url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&ssl=1","width":1024,"height":608},{"@type":"BreadcrumbList","@id":"https:\/\/blexin.com\/it\/blog\/creiamo-la-nostra-api-con-graphql-e-hot-chocolate\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blexin.com\/it\/"},{"@type":"ListItem","position":2,"name":"Creiamo la nostra API con GraphQL e Hot Chocolate"}]},{"@type":"WebSite","@id":"https:\/\/blexin.com\/it\/#website","url":"https:\/\/blexin.com\/it\/","name":"Blexin","description":"Con noi \u00e8 semplice","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blexin.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/0de430b61c8a48b0e9d81308817c1517","name":"Adolfo Arnold","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g","caption":"Adolfo Arnold"},"url":"https:\/\/blexin.com\/it\/author\/adolfo-arnoldblexin-com\/"}]}},"jetpack_publicize_connections":[],"jetpack_likes_enabled":false,"jetpack_shortlink":"https:\/\/wp.me\/pcyUBx-749","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/top00-3.png?fit=1024%2C608&ssl=1","_links":{"self":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/27165","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/users\/196716250"}],"replies":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/comments?post=27165"}],"version-history":[{"count":3,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/27165\/revisions"}],"predecessor-version":[{"id":27802,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/27165\/revisions\/27802"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media\/27129"}],"wp:attachment":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media?parent=27165"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/categories?post=27165"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/tags?post=27165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}