{"id":28365,"date":"2019-07-23T00:00:00","date_gmt":"2019-07-22T22:00:00","guid":{"rendered":"https:\/\/blexin.com\/?p=28365"},"modified":"2021-01-13T09:40:29","modified_gmt":"2021-01-13T08:40:29","slug":"visual-studio-code-nella-tua-app","status":"publish","type":"post","link":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/","title":{"rendered":"Visual Studio Code nella tua App!"},"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=\"28366\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/attachment\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&amp;ssl=1\" data-orig-size=\"1024,608\" data-comments-opened=\"0\" data-image-title=\"ef2482d2-a0c4-4f26-b70a-3dcc8afa5923\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?resize=1024%2C608&#038;ssl=1\" alt=\"\" class=\"wp-image-28366\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923-980x582.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923-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\">Durante un\u2019attivit\u00e0 di consulenza presso un cliente che aveva commissionato lo sviluppo di una piattaforma di e-commerce, ci \u00e8 stato chiesto se e come fosse possibile consentire agli utenti di&nbsp;<em>customizzare<\/em>&nbsp;la propria interfaccia modificando stili e temi delle pagine, e salvarli su una sorgente dati, magari versionandoli, in modo da consentirne il recupero.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Abbiamo quindi stilato una lista dei diversi problemi da affrontare:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>versioning<\/strong>: definire una modalit\u00e0 di versionamento dei file, magari prendendo in considerazione anche le versioni non definitive (draft);<\/li><li><strong>editing<\/strong>&nbsp;inline: modifica dei file, possibilmente tramite colorazione di sintassi;<\/li><li><strong>comparing<\/strong>: confronto dei files con versioni precedenti;<\/li><li><strong>provisioning<\/strong>: definire una modalit\u00e0 di recupero dei file.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">La piattaforma e-commerce era basata sul framework&nbsp;<strong>ASP.NET MVC 5<\/strong>. Ci\u00f2 ci ha spinto a cercare soluzioni compatibili con l\u2019ambiente&nbsp;<strong>.NET<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per le attivit\u00e0 di modifica dei file, la scelta \u00e8 ricaduta su&nbsp;<strong>Monaco Editor<\/strong>, strumento che \u00e8 anche motore di&nbsp;<strong>Visual Studio Code<\/strong>: supportato da tutti i principali browser, e che fornisce una serie di facilitazioni, come la colorazione del testo basata sul linguaggio scelto, l\u2019<strong><em>intellisense<\/em><\/strong>&nbsp;e il&nbsp;<strong><em>diff<\/em><\/strong>&nbsp;dei files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Monaco Editor risulta di facile installazione e configurazione, dal momento che necessita del link a una libreria JS e, tramite le API documentate (<a href=\"https:\/\/microsoft.github.io\/monaco-editor\/api\/index.html\">API Monaco Editor<\/a>), \u00e8 possibile ottenere un\u2019istanza pronta ad essere utilizzata. Ad esempio, l\u2019istruzione:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nmonaco.editor.create(document.getElementById(&quot;container&quot;), {\n\u00a0\u00a0\u00a0\u00a0value: &quot;function hello() {\\n\\t alert(&#039;Hello world!&#039;);\\n}&quot;,\n\u00a0\u00a0\u00a0\u00a0language: &quot;javascript&quot;\n});\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">sulla pagina:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;div id=&quot;container&quot; style=&quot;height:100%;&quot;&gt;&lt;\/div&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">genera la schermata:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"952\" height=\"175\" data-attachment-id=\"28371\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/attachment\/image01-19\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-19.png?fit=952%2C175&amp;ssl=1\" data-orig-size=\"952,175\" data-comments-opened=\"0\" data-image-title=\"image01-19\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-19.png?fit=952%2C175&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-19.png?resize=952%2C175&#038;ssl=1\" alt=\"\" class=\"wp-image-28371\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-19.png 952w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-19-480x88.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 952px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Nel nostro caso, abbiamo utilizzato l\u2019editor sia per modificare che per confrontare le varie versioni dei files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per definire i file che possono essere modificati abbiamo creato la classe&nbsp;<strong>EditableContent<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class EditableContent\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;Key]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;Required]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public string Path { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public string Type { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(false)]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public bool Disabled { get; set; }\n\u00a0\u00a0\u00a0\u00a0} \n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">L\u2019attributo Type serve alla corretta visualizzazione del file su Monaco Editor, dal momento che, come scritto prima, \u00e8 possibile definire di che tipo \u00e8 il file, al fine di ottenere la colorazione del testo e segnalazione degli errori.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per i file gi\u00e0 modificati, invece, abbiamo la classe&nbsp;<strong>StoredContent<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class StoredContent\n{\n\u00a0\u00a0\u00a0\u00a0&#x5B;Key]\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Required]\n\u00a0\u00a0\u00a0\u00a0public string Path { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Required]\n\u00a0\u00a0\u00a0\u00a0public string Content { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Required]\n\u00a0\u00a0\u00a0\u00a0public int Version { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(false)]\n\u00a0\u00a0\u00a0\u00a0public bool Draft { get; set; }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In StoredContent, quindi, \u00e8 presente sia il numero di versione sia l\u2019attributo draft che ci indica se si tratti di una versione definitiva.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per le operazioni&nbsp;<em>CRUD (Create, Read, Update e Delete)<\/em>&nbsp;dei files, abbiamo creato il controller API&nbsp;<strong>ContentsController<\/strong>, che presenta i seguenti metodi:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>IEnumerable&lt;string&gt; GetEditableContents(): serve ad ottenere la lista dei contenuti modificabili;<\/li><li>IEnumerable&lt;StoredContentVersionModel&gt; GetContentAvailableVersions(BaseContentModel baseContent): ottiene la lista delle versioni disponibili per il path specificato;<\/li><li>string GetContent(StoredContentModel storedContent): ottiene il contenuto di un file a partire dal percorso e dal numero di versione;<\/li><li>StoredContentModel GetLatestContent(BaseContentModel baseContent): ottiene il contenuto di un file a partire dal percorso e relativo all&#8217;ultima versione disponibile;<\/li><li>int CreateStoredContent(StoredContentModel storedContent): crea una nuova versione di un file;<\/li><li>int RecoverStoredContentVersion([FromBody] StoredContentModel storedContent): recupera una versione precedentemente salvata e la importa come ultima.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>BaseContentModel, StoredContentModel, StoredContentVersionModel<\/strong>&nbsp;sono viewmodel utilizzati per lo scambio dei dati con le view, e sono cos\u00ec definite:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class BaseContentModel\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public string Path { get; set; }\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public class StoredContentVersionModel \n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public int Version { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public bool Draft { get; set; }\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public class StoredContentModel : BaseContentModel\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public string Content { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public string Type { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public bool? Draft { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public int Version { get; set; }\n\u00a0\u00a0\u00a0\u00a0}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Nello specifico, l&#8217;implementazione presenta alcuni punti da definire meglio, come ad esempio&nbsp;<strong>GetLatestContent<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic StoredContentModel GetLatestContent(&#x5B;FromBody] BaseContentModel baseContent)\n{\n\u00a0\u00a0\u00a0\u00a0var storedContent = _context.StoredContents\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Where(sc =&gt; sc.Path == baseContent.Path)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.OrderByDescending(sc =&gt; sc.Version).FirstOrDefault();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0if (storedContent == null)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var webRoot = _env.WebRootPath;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var file = System.IO.Path.Combine(webRoot, baseContent.Path);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0storedContent = new StoredContent()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Path = baseContent.Path,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Content = System.IO.File.ReadAllText(file, System.Text.Encoding.Default),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Version = 0,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Draft = false\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_context.StoredContents.Add(storedContent);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_context.SaveChanges();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0return new StoredContentModel()\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;...]\n\u00a0\u00a0\u00a0\u00a0};\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Quando non c\u2019\u00e8 nessun file corrispondente su db, viene creata una versione 0, in cui c&#8217;\u00e8 il contenuto del file presente su file system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">GetLatestContent viene invocato da una chiamata Ajax tramite jquery:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nfunction loadPage(path) {\n\u00a0\u00a0\u00a0\u00a0$.ajax({\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0url: &quot;\/api\/contents\/GetLatestContent&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0type: &quot;POST&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data: JSON.stringify({Path: path }),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0contentType: &quot;application\/json; charset=utf-8&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataType: &quot;json&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0success: function (data) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0setMonacoEditor(data.content, data.type, data.path);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0})\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">dove setMonacoEditor() inizializza l&#8217;editor in modalit\u00e0 lettura e modifica del singolo file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nfunction setMonacoEditor(text, mode, path) {\n\u00a0\u00a0\u00a0\u00a0if (!editor) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$(&#039;#editor&#039;).empty();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0editor = monaco.editor.create(document.getElementById(&#039;editor&#039;), {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0model: null,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0automaticLayout: true\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0var oldModel = editor.getModel();\n\u00a0\u00a0\u00a0\u00a0var newModel = monaco.editor.createModel(text, mode);\n\u00a0\u00a0\u00a0\u00a0editor.setModel(newModel);\n\u00a0\u00a0\u00a0\u00a0if (oldModel) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0oldModel.dispose();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\/\/&#x5B;...]\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Per salvare il nuovo contenuto, c&#8217;\u00e8 il metodo&nbsp;<strong>CreateStoredContent<\/strong>&nbsp;che crea una nuova versione del file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic int CreateStoredContent(&#x5B;FromBody] StoredContentModel storedContent)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var storedContentToCreate = new StoredContent()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Content = storedContent.Content,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Path = storedContent.Path,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Draft = storedContent.Draft.GetValueOrDefault(false)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var latestStoredContent = _context.StoredContents\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Where(sc =&gt; sc.Path == storedContent.Path)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.OrderByDescending(sc =&gt; sc.Version).FirstOrDefault();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (latestStoredContent == null){\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0storedContentToCreate.Version = 1;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else if (latestStoredContent.Draft){\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0storedContentToCreate.Version = latestStoredContent.Version;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0storedContentToCreate.Version = ++latestStoredContent.Version;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_context.StoredContents.Add(storedContentToCreate);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_context.SaveChanges();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return storedContentToCreate.Id;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Da notare la gestione del numero di versione tramite il flag Draft impostato. Se l\u2019ultima versione presente sul db \u00e8&nbsp;<strong>draft<\/strong>, allora non si incrementa di numero di versione, altrimenti dipende dal flag passato al servizio.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nel nostro esempio, in cui abbiamo posto come modificabile il file site.css, la finestra appare cos\u00ec:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"551\" data-attachment-id=\"28376\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/attachment\/image02-18\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-18.png?fit=1597%2C859&amp;ssl=1\" data-orig-size=\"1597,859\" data-comments-opened=\"0\" data-image-title=\"image02-18\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-18.png?fit=1024%2C551&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-18.png?resize=1024%2C551&#038;ssl=1\" alt=\"\" class=\"wp-image-28376\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-18-980x527.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-18-480x258.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\">Per il diff dei files, richiamiamo un altro metodo di ContentsController,&nbsp;<strong>GetContent<\/strong>, e nel&nbsp;<em>body<\/em>&nbsp;passiamo path e numero di versione.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic string GetContent(&#x5B;FromBody] StoredContentModel storedContent)\n{\n\u00a0\u00a0\u00a0\u00a0var _storedContent = _context.StoredContents.FirstOrDefault(sc =&gt; sc.Path == storedContent.Path &amp;&amp; sc.Version == storedContent.Version);\n\u00a0\u00a0\u00a0\u00a0if (_storedContent != null)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return _storedContent.Content;\n\u00a0\u00a0\u00a0\u00a0else\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return &quot;&quot;;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Lato front-end, invece abbiamo il metodo javascript&nbsp;<strong>loadPageDiff<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nfunction loadPageDiff(path, newversion, oldversion, mode) {\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var onError = function () {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$(&#039;.loading.diff-editor&#039;).fadeOut({ duration: 200 });\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$(&#039;#diff-editor&#039;).append(&#039;&lt;p class=&quot;alert alert-error&quot;&gt;Failed to load diff editor sample&lt;\/p&gt;&#039;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$(&#039;.loading.diff-editor&#039;).show();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var lhsData = null, rhsData = null, jsMode = null;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$.ajax({\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0url: &quot;\/api\/contents\/GetContent&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0type: &quot;POST&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data: JSON.stringify({ Path: path, Version: newversion }),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0contentType: &quot;application\/json; charset=utf-8&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataType: &quot;text&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0success: function (data) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lhsData = data;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0onProgress();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0})\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$.ajax({\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0url: &quot;\/api\/contents\/GetContent&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0type: &quot;POST&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data: JSON.stringify({ Path: path, Version: oldversion }),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0contentType: &quot;application\/json; charset=utf-8&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataType: &quot;text&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0success: function (data) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0rhsData = data;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0onProgress();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0})\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0function onProgress() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ set diff environment\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">che richiama due volte GetContent e posiziona le versioni in finestre affiancate, in modo da consentire all\u2019utente di verificare al meglio le modifiche fatte al file e confrontare con le versioni precedenti.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La funzionalit\u00e0 di recupero viene garantita dal metodo RecoverStoredContentVersion<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic int RecoverStoredContentVersion(&#x5B;FromBody] StoredContentModel storedContent)\n{\n\u00a0\u00a0\u00a0\u00a0var versionedStoredContent = _context.StoredContents\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Where(sc =&gt; sc.Path == storedContent.Path &amp;&amp; sc.Version == storedContent.Version)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.FirstOrDefault();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0var latestStoredContentVersion = _context.StoredContents\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Where(sc =&gt; sc.Path == storedContent.Path)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Max(sc =&gt; sc.Version);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0var storedContentToCreate = new StoredContent()\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Path = storedContent.Path,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Content = versionedStoredContent.Content,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Version = ++latestStoredContentVersion,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Draft = false\n\u00a0\u00a0\u00a0\u00a0};\n\u00a0\n\u00a0\u00a0\u00a0\u00a0_context.StoredContents.Add(storedContentToCreate);\n\u00a0\u00a0\u00a0\u00a0_context.SaveChanges();\n\u00a0\u00a0\u00a0\u00a0return storedContentToCreate.Id;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Nel nostro esempio, la finestra in diff appare cos\u00ec:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"486\" data-attachment-id=\"28379\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/attachment\/image03-16\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-16.png?fit=1539%2C731&amp;ssl=1\" data-orig-size=\"1539,731\" data-comments-opened=\"0\" data-image-title=\"image03-16\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-16.png?fit=1024%2C486&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-16.png?resize=1024%2C486&#038;ssl=1\" alt=\"\" class=\"wp-image-28379\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-16-980x465.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-16-480x228.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\">Il recupero dei file modificati non \u00e8 oggetto di questo articolo, ma vorremmo introdurre due classi importanti. Su .NET Framework, nella libreria System.Web.Hosting, c&#8217;\u00e8 la classe&nbsp;<strong>VirtualPathProvider<\/strong>&nbsp;(<a href=\"https:\/\/docs.microsoft.com\/it-it\/dotnet\/api\/system.web.hosting.virtualpathprovider?view=netframework-4.8\">qui<\/a>), che definisce la creazione di un file system virtuale a partire da un insieme di dati di varia natura e consente di creare delle logiche di recupero customizzate e caching dei file tramite l\u2019override di una serie di metodi:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>VirtualFile GetFile(string virtualPath): Permette di recuperare un file, sia dal path fisico che da quello virtuale;<\/li><li>bool FileExists(string virtualPath): Consente di verificare se esiste un file virtuale;<\/li><li>CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart): Gestisce il caching dei files virtuali;<\/li><li>String GetFileHash(String virtualPath, IEnumerable virtualPathDependencies): Restituisce un hash del file specificato.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Su .NET Core c&#8217;\u00e8 l&#8217;interfaccia&nbsp;<strong>IfileProvider<\/strong>&nbsp;(<a href=\"https:\/\/www.blexin.com\/it-IT\/Article\/Blog\/%E2%80%9Dhttps:\/\/docs.microsoft.com\/it-it\/aspnet\/core\/fundamentals\/file-providers?view=aspnetcore-2.2\">qui<\/a>) che, analogamente a VirtualPathProvider, definisce le logiche di recupero dei file da varie sorgenti tramite l&#8217;implementazione di alcuni metodi:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>IDirectoryContents GetDirectoryContents(string subpath): Restituisce il contenuto di una directory;<\/li><li>IFileInfo GetFileInfo(string subpath): Restituisce un oggetto di tipo FileInfo (contiene la logica di business);<\/li><li>IChangeToken Watch(string filter): Definisce le modalit\u00e0 per verificare se il file richiesto \u00e8 cambiato o meno rispetto all&#8217;ultimo utilizzo.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Un esempio di utilizzo di IFileProvider, oltre al codice utilizzato nell\u2019articolo, \u00e8 disponibile qui:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/enricobencivenga\/MonacoEditor\">https:\/\/github.com\/enricobencivenga\/MonacoEditor<\/a><\/p>\n\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>Integriamo Monaco, l\u2019editor alla base di Visual Studio Code, nelle nostre applicazioni web<\/p>\n","protected":false},"author":196716247,"featured_media":28366,"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_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":[688637419,688637445],"class_list":["post-28365","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-asp-net","tag-vscode"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Visual Studio Code nella tua App! - 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\/visual-studio-code-nella-tua-app\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Visual Studio Code nella tua App! - Blexin\" \/>\n<meta property=\"og:description\" content=\"Integriamo Monaco, l\u2019editor alla base di Visual Studio Code, nelle nostre applicazioni web\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/\" \/>\n<meta property=\"og:site_name\" content=\"Blexin\" \/>\n<meta property=\"article:published_time\" content=\"2019-07-22T22:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-13T08:40:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.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=\"Enrico Bencivenga\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Enrico Bencivenga\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/\"},\"author\":{\"name\":\"Enrico Bencivenga\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/74e4443d1d7ad12d5b4a8db7f63f0194\"},\"headline\":\"Visual Studio Code nella tua App!\",\"datePublished\":\"2019-07-22T22:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/\"},\"wordCount\":916,\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1\",\"keywords\":[\"Asp.net\",\"VScode\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/\",\"name\":\"Visual Studio Code nella tua App! - Blexin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1\",\"datePublished\":\"2019-07-22T22:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:29+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/74e4443d1d7ad12d5b4a8db7f63f0194\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1\",\"width\":1024,\"height\":608},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/visual-studio-code-nella-tua-app\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blexin.com\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Visual Studio Code nella tua App!\"}]},{\"@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\\\/74e4443d1d7ad12d5b4a8db7f63f0194\",\"name\":\"Enrico Bencivenga\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g\",\"caption\":\"Enrico Bencivenga\"},\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/author\\\/enrico-bencivengablexin-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Visual Studio Code nella tua App! - 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\/visual-studio-code-nella-tua-app\/","og_locale":"it_IT","og_type":"article","og_title":"Visual Studio Code nella tua App! - Blexin","og_description":"Integriamo Monaco, l\u2019editor alla base di Visual Studio Code, nelle nostre applicazioni web","og_url":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/","og_site_name":"Blexin","article_published_time":"2019-07-22T22:00:00+00:00","article_modified_time":"2021-01-13T08:40:29+00:00","og_image":[{"width":1024,"height":608,"url":"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1","type":"image\/png"}],"author":"Enrico Bencivenga","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Enrico Bencivenga","Tempo di lettura stimato":"7 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/#article","isPartOf":{"@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/"},"author":{"name":"Enrico Bencivenga","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/74e4443d1d7ad12d5b4a8db7f63f0194"},"headline":"Visual Studio Code nella tua App!","datePublished":"2019-07-22T22:00:00+00:00","dateModified":"2021-01-13T08:40:29+00:00","mainEntityOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/"},"wordCount":916,"image":{"@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1","keywords":["Asp.net","VScode"],"articleSection":["Blog"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/","url":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/","name":"Visual Studio Code nella tua App! - Blexin","isPartOf":{"@id":"https:\/\/blexin.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/#primaryimage"},"image":{"@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1","datePublished":"2019-07-22T22:00:00+00:00","dateModified":"2021-01-13T08:40:29+00:00","author":{"@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/74e4443d1d7ad12d5b4a8db7f63f0194"},"breadcrumb":{"@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/#primaryimage","url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1","width":1024,"height":608},{"@type":"BreadcrumbList","@id":"https:\/\/blexin.com\/it\/blog\/visual-studio-code-nella-tua-app\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blexin.com\/it\/"},{"@type":"ListItem","position":2,"name":"Visual Studio Code nella tua App!"}]},{"@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\/74e4443d1d7ad12d5b4a8db7f63f0194","name":"Enrico Bencivenga","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g","caption":"Enrico Bencivenga"},"url":"https:\/\/blexin.com\/it\/author\/enrico-bencivengablexin-com\/"}]}},"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/pcyUBx-7nv","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ef2482d2-a0c4-4f26-b70a-3dcc8afa5923.png?fit=1024%2C608&ssl=1","_links":{"self":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28365","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\/196716247"}],"replies":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/comments?post=28365"}],"version-history":[{"count":9,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28365\/revisions"}],"predecessor-version":[{"id":28385,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28365\/revisions\/28385"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media\/28366"}],"wp:attachment":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media?parent=28365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/categories?post=28365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/tags?post=28365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}