<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>ASP.NET Web Api</title>
        <link>http://blogs.ugidotnet.org/PietroLibroBlog/category/ASP.NET Web Api.aspx</link>
        <description>ASP.NET Web Api</description>
        <language>it-IT</language>
        <copyright>Pietro Libro</copyright>
        <managingEditor>pietro.libro@libero.it</managingEditor>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>Asp.Net 5, MVC 6 e Web Api</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/11/23/asp.net-5-mvc-6-e-web-api.aspx</link>
            <description>E’ qualche mese che non scrivo nulla sul blog, ma gli studi, come la vita, sono andata avanti. Ora eccoci qui a fare qualche test con le nuove versioni delle ultime tecnologie\framework web del mondo Microsoft, che ci regala ogni giorno qualcosa di tecnlogicamente fantastico…alla faccia dei soliti criticoni . Torniamo con i piedi per terra e proviamo ad utilizzare le Web Api in un progetto MVC 6 (attualmente in versione beta, ASP.NET 5 fonde i framework MCV e Web Api). Apriamo il nostro VS 2015 preview (scaricabile nella versione ultimate a questo indirizzo: ) e creiamo un nuovo progetto “ASP.NET Web Application”:    Poi selezioniamo il template ASP.NET 5 Empty:    Attendiamo qualche secondo che Visual Studio crei l’alberatura della soluzione con tutti i relativi file:    Notiamo due file in formato “.json”, global.json e project.json, che possiamo editare rispettivamente per i settings e per le references a livello globale (solution) o di singolo progetto. La classe Startup.cs ed in particolare il metodo Configure(…) definisce l’entry point della pipeline di ASP.NET, ed è qui che andremo ad aggiungere il codice necessario all’esecuzione dell’applicazione. Prima, apriamo il file project.json, e nella sezione dependencies aggiungiamo la riga seguente:  "Microsoft.AspNet.Mvc": "6.0.0-beta1"

Notare come l’editor sia completo di IntelliSense che ci permette di scegliere dinamicamente package e versione (tra quelle disponibili):



Inizializziamo MVC nella classe Startup.cs, aggiungendo il metodo ConfigureServices:

1 public void ConfigureServices(IServiceCollection services) 
2 { 
3     services.AddMvc(); 
4 }

il quale aggiunge tutte le dipendenze di cui MVC 6 ha bisogno. Utilizziamo il metodo d’estensione UseMvc nel metodo Configure:

1 public void Configure(IApplicationBuilder app) 
2 {            
3     app.UseMvc(); 
4 } 

Aggiungiamo una classe ItemsController (“Web Api Controller Class”) nella classica cartella di progetto Controllers:



 1 [Route("api/[controller]")] 
 2 public class ItemsController : Controller 
 3 { 
 4     // GET: api/values 
 5     [HttpGet] 
 6     public IEnumerable&amp;lt;Item&amp;gt; Get() 
 7     { 
 8         return new List&amp;lt;Item&amp;gt;( 
 9             new Item[]{ 
10                 new Item() { Code= "Item#1", Description= "Item_Description#1" }, 
11                 new Item() { Code = "Item2", Description = "Item_Description#2"} }); 
12     } 
13 }

Poi aggiungiamo la classe Item:

1 public class Item 
2 { 
3     public string Code { get; set; } 
4     public string Description { get; set; } 
5 }

Avviamo il progetto ed invochiamo via browser il servizio:



Il servizio dovrebbe restituire il seguente json :

1 [{"Code":"Item#1","Description":"Item_Description#1"}
2 ,{"Code":"Item2","Description":"Item_Description#2"}]

Notiamo come la classe ItemsController a differenza delle versioni precedenti, non derivi piu’ dalla classe ApiController, ma direttamente da Controller. Se proviamo ad utilizzare uno strumento come Fiddler per analizzare le request e le response delle nostre Api, possiamo scoprire qualcosa di interessante, se ad esempio, modifichiamo la nostra Web Api in modo da tornare null, con l’attuale versione di ASP.NET Web Api otterremmo:



Ovvero una response con status 200 e corpo del messaggio vuoto, con la versione MVC 6 invece:



Una response con status 204 (No Content), che logicamente parlando IMHO è piu’ corretta (la risposta è OK, ma il contenuto del body è vuoto). Ulteriori dettagli sui Formatters in MVC6 possono essere trovati in questo post di Filip W. Per ritornare ad avere un comportamento Old Style è sufficiente agire a livello di configurazione, in ConfigureServices:

1 public void ConfigureServices(IServiceCollection services) 
2 { 
3     services.AddMvc().Configure&amp;lt;MvcOptions&amp;gt;(o =&amp;gt; o.OutputFormatters 
4     .RemoveAll(f =&amp;gt; f.Instance.GetType() == typeof(HttpNoContentOutputFormatter))); 
5 }

Ovviamente di novità ci sono e tante, ma almeno sappiamo da dove iniziare  .

  &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101903.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/11/23/asp.net-5-mvc-6-e-web-api.aspx</guid>
            <pubDate>Sun, 23 Nov 2014 10:17:55 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/11/23/asp.net-5-mvc-6-e-web-api.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101903.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101903.aspx</trackback:ping>
        </item>
        <item>
            <title>JSON.Merge</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/08/29/json.merge.aspx</link>
            <description>Un’interessante novità introdotta con la versione 6.0 release 4 di Json.NET è la possibilità di eseguire il Merge (utilizzando 4 possibili “variazioni”) di oggetti JObject e Jarray. Un rapido esempio, tramite Web Api:  [HttpPost]        
public void JsonStringPost([FromBody]string value)
{
    JObject jCar = JObject.Parse(value);
    JObject jOptional = JObject.Parse(@"{Optionals :['Air Conditioned','Smoker'] }");

    jCar.Merge(jOptional, new JsonMergeSettings() { MergeArrayHandling = MergeArrayHandling.Union });

    string jsonFormat = jCar.ToString();
    Car mergedCar =  jCar.ToObject&amp;lt;Car&amp;gt;(); 
}

Dove l’Action “JsonStringPost” accetta una stringa tipo:

"{ 'Brand': 'Ferrari','Model': 'f450 Modena','Optionals': [] }"

Utilizzando, ad esempio il Composer di strumenti come Fiddler2 possiamo invocare il servizio:
 

Per ottenere una nuova istanza di Car con tutti gli Optionals:



Se il nostro servizio accetta direttamente un’istanza di oggetto invece di una stringa in formato JSON, il nostro codice cambia leggermente, come di seguito:

[HttpPost]
public void JsonObjectPost([FromBody] Car carByPost)
{
    JObject jCar = JObject.FromObject(carByPost);

    JObject jOptional = JObject.Parse(@"{Optionals :['Air Conditioned','Smoker'] }");
    jCar.Merge(jOptional, new JsonMergeSettings() { MergeArrayHandling = MergeArrayHandling.Union });

    string jsonFormat = jCar.ToString();
    Car mergedCar = jCar.ToObject();
}

Dove utilizziamo il metodo FromObject della classe JObject invece di Parse. Utilizzando Fiddler, passando come Body del messaggio la stringa (senza i doppi apici ad inizio e fine stringa)

{ 'Brand': 'Ferrari','Model': 'f450 Modena','Optionals': [] }

Otteniamo (ovviamente) lo stesso risultato dell’invocazione precedente. E’ possibile modificare il comportamento di “Merge” utilizzando l’enumerazione MergeArrayHandling. La classe Car (C#) è descritta nell’esempio, è la seguente:

public class Car
{
    public string Brand { get; set; }
    public string Model { get; set; }
    public string[] Optionals { get; set; }
}

La lista completa delle features aggiunte nel rilascio della versione 6.0 release 4 è disponibile qui.&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101880.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/08/29/json.merge.aspx</guid>
            <pubDate>Fri, 29 Aug 2014 13:30:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/08/29/json.merge.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101880.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101880.aspx</trackback:ping>
        </item>
        <item>
            <title>Request Batching in Web Api 2</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/23/request-batching-in-web-api-2.aspx</link>
            <description>Una funzionalità molto interessante introdotta con ASP.NET Web API 2 OData è il supporto “Batching”, ovvero la possibilità di “impacchettare” in una singola richiesta HTTP piu’ richieste Web API (action) e ricevere in un’unica risposta HTTP i risultati ottenuti dalle singole invocazioni delle Web API. Questa funzionalità è molto interessante in quanto ci permette di minimizzare il numero di richieste\risposte tra client e server, riducendo il traffico di rete (pensiamo al Cloud…).   Per abilitare Server Side questa funzionalità è necessario esporre tramite registrazione, un HTTP batch endpoint utilizzando il metodo MapHttpBatchRoute esposto dall’instanza Routes della classe HttpRouteCollection:config.Routes.MapHttpBatchRoute(
        routeName: "BatchApi",
        routeTemplate: "api/batch",
        batchHandler: new System.Web.Http.Batch.DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer));


 
Il codice del Controller Web Api è relativamente semplice (è in allegato) ed è stato utilizzato come DEMO per la mia sessione durante l’ultimo l’evento organizzato da DomusDotNet. A questo punto la palla passa Client Side, dove tramite un’unica chiamata HTTP vogliamo ottenere l’elenco di tutte le entità Car serializzate, l’inserimento di una nuova entità Car e la modifica del valore di una proprietà di un’entità precedentemente recuperata.
Iniziamo con il recuperare l’entità Car con Id=1HttpClient client = new HttpClient();
string response = await client.GetStringAsync("http://localhost:31613/Api/Cars/1");

Car car = (Newtonsoft.Json.JsonConvert.DeserializeObject(response)
    as Newtonsoft.Json.Linq.JObject).ToObject&amp;lt;Car&amp;gt;();


 
Poi un HttpRequestMessage per ottenere (GET) l’elenco di tutte le entità:HttpRequestMessage getCars = new HttpRequestMessage(HttpMethod.Get, http://localhost:31613/Api/Cars); 


Un altro HttpRequestMessage per aggiungere (POST) una nuova entità:JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
HttpRequestMessage postCar = new HttpRequestMessage(HttpMethod.Post, "http://localhost:31613/Api/Cars");
postCar.Content = new ObjectContent&amp;lt;Car&amp;gt;(new Car()
{
    Brand_Id = 1,
    DailyRent = 50.0f,
    EngineSize = "2500",
    Model = "GTV",
    Note = "---"
},formatter); 


Ed infine un HttpRequestMessage per aggiornare (PUT) l’entità Car precedentemente recuperata:car.Note += " BATCH";
HttpRequestMessage putCar = new HttpRequestMessage(HttpMethod.Put,
    string.Format("http://localhost:31613/Api/Cars?id={0}", car.Id));
putCar.Content = new ObjectContent&amp;lt;dynamic&amp;gt;(car, formatter); 


a questo punto, dobbiamo “impacchettare” le singole richieste in un’unica richiesta HTTP, utilizzanto un’istanza di MultiPartContent:HttpMessageContent getCarsContent = new HttpMessageContent(getCars);
HttpMessageContent postCarContent = new HttpMessageContent(postCar);
HttpMessageContent putCarContent = new HttpMessageContent(putCar);

MultipartContent multiPartContent = new MultipartContent("mixed", "batch_" + Guid.NewGuid().ToString());
multiPartContent.Add(getCarsContent);
multiPartContent.Add(postCarContent);
multiPartContent.Add(putCarContent);

HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, "http://localhost:31613/api/batch");
batchRequest.Content = multiPartContent; 


Non ci resta che effettuare la richiesta al Server:HttpResponseMessage multipartResponse = await client.SendAsync(batchRequest);
MultipartMemoryStreamProvider responseContents = await multipartResponse.Content.ReadAsMultipartAsync(); 


e recuperare le singole risposte:////Status Code: 200, Ok.
HttpResponseMessage getResponse = await responseContents.Contents[0].ReadAsHttpResponseMessageAsync();
////Status Code: 201, Created.
HttpResponseMessage postResponse = await responseContents.Contents[1].ReadAsHttpResponseMessageAsync();
////Status Code:204, Not Content.
HttpResponseMessage putResponse = await responseContents.Contents[2].ReadAsHttpResponseMessageAsync();
 
Normalmente le singole richieste contenute all’interno di un “batch” sono eseguite sequenzialmente, di conseguenza in questo caso, la richiesta di POST partirebbe subito dopo quella di GET ed immediatamente prima di quella di PUT. Se l’ordine di esecuzione non è importante, possiamo eseguire le richieste in modo asincrono impostando la proprietà ExecutionOrder a BatchExecutionOrder.NonSequential:config.Routes.MapHttpBatchRoute(
    routeName: "BatchApi",
    routeTemplate: "api/batch",
    batchHandler: new System.Web.Http.Batch.DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer)
    {
        ExecutionOrder = System.Web.Http.Batch.BatchExecutionOrder.NonSequential
    }); 


Attach Cars Controller Code&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101749.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/23/request-batching-in-web-api-2.aspx</guid>
            <pubDate>Mon, 23 Dec 2013 12:49:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/23/request-batching-in-web-api-2.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101749.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101749.aspx</trackback:ping>
        </item>
        <item>
            <title>Web Api e Debug su Azure</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/11/19/web-api-e-debug-su-azure.aspx</link>
            <description>Se abbiamo la necessità di debuggare le nostre Web Api pubblicate su Azure, i passi da seguire sono veramente pochi e semplici:     Download ed installazione di Azure SDK 2.2     Aprire la Solution contenente il progetto Web con la definizione delle Web API     Connettersi a Windows Azure tramite l’apposito link in Server Explorer:                          Pubblicare il progetto (in Debug):                             Utilizzare la funzione Attach debugger per il Web Site oggetto del Debug:                        Si apre una nuova finestra del Browser con il Web Site     Aggiungiamo dove necessario i breakpoint nel codice (ad esempio su un’azione di GET del nostro Controller)     Invochiamo l’URL e per “magia” (la prima volta puo’ impiegare qualche di tempo) ci troviamo a debuggare la nostra applicazione appena pubblicata:            N.B: I passi precedenti si riferiscono all’utilizzo di VS 2013, per VS 2012 bisogna abilitare il remote debugging tramite il portale della nostra sottoscrizione Azure  &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101726.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/11/19/web-api-e-debug-su-azure.aspx</guid>
            <pubDate>Tue, 19 Nov 2013 10:40:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/11/19/web-api-e-debug-su-azure.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101726.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101726.aspx</trackback:ping>
        </item>
        <item>
            <title>VS 2013 (Preview) : ASP.NET External Authentication</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/07/vs-2013-preview-external-authentication.aspx</link>
            <description>Tra le novità di Visual Studio 2013 ed ASP.NET 4.5.1 , troviamo nuove opzioni per integrare applicazioni SPA (Single Page Application) e Web API (ma non solo) con servizi di autenticazione esterni basati su Social come Twitter, Facebook, Google e Microsoft Accounts o basati su OAuth/OPenID (tutto a vantaggio di noi sviluppatori). Vediamo con un esempio.  Apriamo VS 2013 (Preview) e selezioniamo come template “ASP.NET Web Application”:    Scegliamo il progetto di tipo SPA  che di base utilizza HTML5, CSS3 e ASP.NET Web API (una semplice applicazione “Todo List”):    A questo punto il gioco è quasi finito, nella Solution Explorer apriamo il file App_Start\Startup.Auth.cs e decommentiamo la riga relativa “UseGoogleAuthentication”:    Eseguiamo l’applicazione con F5, e dalla schermata principale possiamo scegliere se autenticarci in modalità classica oppure utilizzando un servizio di autenticazione esterno (nello specifico “Google”):    Decommentando le opportune righe di codice è possibile offrire agli utenti piu’ servizi di autenticazione, ad esempio, per aggiungere anche “Microsoft Authentication” (è necessario possedere un account come developer qui : http://go.microsoft.com/fwlink/?LinkID=144070)  modifichiamo il file di codice precedente aggiungendo “ClientId” and “Client Secret” come richiesto:    Eseguiamo con F5, ed ecco il risultato:    Semplice, no ?  Tutti gli approfondimenti del caso, sul sito di ASP.NET: http://www.asp.net/web-api/overview/security/external-authentication-services&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101636.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/07/vs-2013-preview-external-authentication.aspx</guid>
            <pubDate>Wed, 07 Aug 2013 10:13:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/07/vs-2013-preview-external-authentication.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101636.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101636.aspx</trackback:ping>
        </item>
        <item>
            <title>ASP.NET and Web Tools 2012.2  : Web Api Help Page</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/03/09/asp.net-and-web-tools-2012.2-web-api-page.aspx</link>
            <description>Con il rilascio dell’aggiornamento ASP.NET 2012.2 di qualche settimana fa,  lo sviluppo di una “Help Page” per Web Api, utilizzando l’apposito Package di NuGet, é un’attività che impegna meno di 5 minuti (per completezza di informazione, era già presente una versione alpha del Package prima del rilascio ufficiale).
1) Dalle “references” del progetto Web da “documentare”, apriamo la finestra per la gestione dei “Packages” di NuGet:
 
2) Cerchiamo la voce “Web Api Help Page” e clicchiamo su “Install” (verranno installate le dipendenze necessarie):
 
3) Al progetto verrà aggiunta l’area “HelpPage” sotto la cartella “Areas”, con tutte le classi necessarie (css compreso):
 
4) La classe XmlDocumentationProvider  che implementa l’interfaccia IDocumentationProvider permette di documentare le nostre API nel caso più semplice utilizzando i commenti che decorano le Web API direttamente nel codice (implementando l’interfaccia IDocumentationProvider é possibile personalizzare questo comportamento).
 
5) Aggiungiamo nel Global.asax.cs la riga di codice seguente:
config.Services.Replace(typeof(IDocumentationProvider), new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/file.xml")));

  
  
  
6) A questo punto non ci resta che eseguire la nostra applicazione e digitare “Help” nella barra degli indirizzi:
 
A questo punto é sufficiente passare alle personalizzazioni del caso :-).&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101466.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/03/09/asp.net-and-web-tools-2012.2-web-api-page.aspx</guid>
            <pubDate>Sat, 09 Mar 2013 14:46:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/03/09/asp.net-and-web-tools-2012.2-web-api-page.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101466.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101466.aspx</trackback:ping>
        </item>
    </channel>
</rss>