BlogServiceHost.Create()

WCF & Azure - Il blog di Fabio Cozzolino

Recent Posts

Tags

My

Twitter

Community

Archives

Email Notifications

Social Bar Widget

March 2009 - Posts

Inversion of Control con WCF e Unity (Parte III)

Dalle puntate precedenti:

Abbiamo visto come poter sviluppare un semplice sistema diIoC con WCF sfruttando Unity. La stessa logica è in realtà applicabile a tutti gli altri framework .NET che forniscono funzionalità di IoC.

Vorrei però arricchire quanto già detto per consentire di sfruttare lo UnityServiceBehavior anche in situazioni in cui tutte le impostazioni vengono gestite direttamente dal file di configurazione, e non da codice come abbiamo precedentemente visto.

Per ottenere questo risultato abbiamo bisogno di sviluppare una particolare estenzione, una classe che eredita dal BehaviorExtensionElement. Sviluppiamo quindi il nostro UnityServiceBehaviorExtensionElement.

  1: public class UnityServiceBehaviorExtensionElement : BehaviorExtensionElement
  2: {
  3:     [ConfigurationProperty("containerName")]
  4:     public string ContainerName
  5:     {
  6:         get
  7:         {
  8:             return (string) base["containerName"];
  9:         }
 10:     }
 11: 
 12:     protected override object CreateBehavior()
 13:     {
 14:         return new UnityServiceBehavior(this.ContainerName);
 15:     }
 16: 
 17:     public override Type BehaviorType
 18:     {
 19:         get { return typeof(UnityServiceBehavior); }
 20:     }
 21: }

La classe dichiara semplicemente due metodi: il primo restituisce l’istanza del behavior, mentre il secondo identifica il tipo di behavior che stiamo costruendo. Nella creazione dell’istanza dell’UnityServiceBehavior viene passato il valore della proprietà ContainerName che contiene il nome della sezione di configurazione relativa al container che vogliamo utilizzare.

Immaginiamo di avere questa configurazione di Unity:

  1: <unity>
  2: 
  3:   <containers>
  4: 
  5:     <container name="BookServiceContainer">
  6:       <types>
  7: 
  8:         <type type="DotNetSide.WCF.IoC.Service.InnerBookService, DotNetSide.WCF.IoC.Service"
  9:               name="inner"/>
 10: 
 11:         <type type="DotNetSide.WCF.IoC.Service.IBookService, DotNetSide.WCF.IoC.Service"
 12:               mapTo="DotNetSide.WCF.IoC.Service.BookService, DotNetSide.WCF.IoC.Service">
 13:           <typeConfig>
 14:             <constructor>
 15:               <param name="innerService" parameterType="DotNetSide.WCF.IoC.Service.InnerBookService, DotNetSide.WCF.IoC.Service">
 16:                 <dependency name="inner" />
 17:               </param>
 18:             </constructor>
 19:           </typeConfig>
 20:         </type>
 21: 
 22:       </types>
 23:     </container>
 24: 
 25:   </containers>
 26: 
 27: </unity>
 28: 

La proprietà ContainerName dovrà riportare il nome BookServiceContainer. Prima di utilizzare lo UnityServiceBehaviorExtensionElement, creiamo il costruttore dello UnityServiceBehavior che accetta come parametro il nome del container:

  1: public UnityServiceBehavior(string containerName)
  2:     : this(GetContainer(containerName))
  3: {
  4: }
  5: 
  6: private static IUnityContainer GetContainer(string containerName)
  7: {
  8:     IUnityContainer unityContainer = null;
  9:     var configurationSection =
 10:         (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
 11: 
 12:     UnityContainerElement unityContainerElement = null;
 13:     if (!string.IsNullOrEmpty(containerName))
 14:     {
 15:         unityContainerElement = configurationSection.Containers[containerName];
 16:     }
 17: 
 18:     if (unityContainerElement == null)
 19:     {
 20:         unityContainerElement =
 21:             configurationSection.Containers.Default;
 22:     }
 23: 
 24:     unityContainer = new UnityContainer();
 25:     unityContainerElement.Configure(unityContainer);
 26: 
 27:     return unityContainer;
 28: }

Il costruttore invoca il metodo privato GetContainer per ottenere l’istanza del container e successivamente chiama il costruttore che accetta il container come parametro passando, appunto, l’istanza appena ottenuta.

Ora possiamo utilizzare la nostra estensione nel file di configurazione. Aggiungiamo un nuovo elemento nella sezione extensions del system.serviceModel:

  1: <system.serviceModel>
  2:   ...
  3:   <extensions>
  4:     <behaviorExtensions>
  5:       <add name="unityService"
  6:            type="DotNetSide.WCF.IoC.Unity.UnityServiceBehaviorExtensionElement, DotNetSide.WCF.IoC.Unity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  7:     </behaviorExtensions>
  8:   </extensions>
  9:   ...
 10: </system.serviceModel>

Inseriamo quindi la configurazione del behavior:

  1: <system.serviceModel>
  2:   ...
  3:   <behaviors>
  4:     <serviceBehaviors>
  5:       <behavior name="DotNetSide.WCF.IoC.Service.BookServiceBehavior">
  6:         <serviceMetadata httpGetEnabled="true"/>
  7:         <serviceDebug includeExceptionDetailInFaults="false"/>
  8:         <unityService containerName="BookServiceContainer" />
  9:       </behavior>
 10:     </serviceBehaviors>
 11:   </behaviors>
 12:   ...
 13: </system.serviceModel>

Ora possiamo creare semplicemente il nostro ServiceHost (non lo UnityServiceHost) ed utilizzarlo normalmente. Questo utilizzo di pone anche come alternativa a quanto visto nella seconda parte (Inversion of Control con WCF e Unity (Parte II)) perchè in questo modo non è più necessario utilizzare il ServiceHostFactory per istanziare il ServiceHost.

Se avete dubbi, chiedete pure …

bye

Posted: Mar 28 2009, 09:25 PM by Fabio.Cozzolino | with no comments
Filed under: , ,
Inversion of Control con WCF e Unity (Parte II)

Questo post è basato sul precedente Inversion of Control con WCF e Unity.

Nel post precedente abbiamo visto in che modo è possibile abilitare l’uso dell’IoC anche per i servizi WCF. Nell’esempio abbiamo visto però come creare il ServiceHost in applicazioni self-hosted. Per utilizzare il tutto anche in applicazioni ASP.NET e quindi in hosting su IIS dobbiamo implementare un ulteriore componente: il ServiceHostFactory.

Implementiamo quindi il nostro UnityServiceHostFactory:

  1: public class UnityServiceHostFactory : ServiceHostFactory
  2: {
  3:     protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
  4:     {
  5:         IUnityContainer unityContainer = null;
  6:         var configurationSection = 
  7:             (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
  8: 
  9:         string configurationName = GetConfigurationName(serviceType);
 10:         var unityContainerElement = 
 11:             configurationSection.Containers[configurationName];
 12:         if (unityContainerElement == null)
 13:         {
 14:             unityContainerElement = 
 15:                 configurationSection.Containers.Default;
 16:         }
 17: 
 18:         if (unityContainerElement != null)
 19:         {
 20:             unityContainer = new UnityContainer();
 21:             unityContainerElement.Configure(unityContainer);
 22:         }
 23: 
 24:         return new UnityServiceHost(unityContainer, serviceType, baseAddresses);
 25:     }
 26: 
 27:     private string GetConfigurationName(Type serviceType)
 28:     {
 29:         ServiceBehaviorAttribute serviceBehaviorAttribute = serviceType.GetCustomAttributes(true)
 30:             .OfType<ServiceBehaviorAttribute>()
 31:             .FirstOrDefault();
 32: 
 33:         return (serviceBehaviorAttribute != null &&
 34:             !string.IsNullOrEmpty(serviceBehaviorAttribute.ConfigurationName))
 35:                    ? serviceBehaviorAttribute.ConfigurationName
 36:                    : serviceType.FullName;
 37:     }
 38: }

Il metodo CreateServiceHost è quello invocato dal ServiceHostingEnvironment per la creazione, appunto, del ServiceHost. In questo metodo creiamo l’istanza dell’UnityContainer e poi la configuriamo sulla base di quanto indicato nel file di configurazione (web.config, in questo caso). La soluzione qui implementata cerca inizialmente, tra i containers, uno specifico il cui nome corrisponde al ConfigurationName eventualmente indicato nell’attributo ServiceBehavior dell’implementazione del servizio. Se non specificato, viene utilizzato il nome completo del tipo del servizio. Se però il container specifico non viene trovato, lo unityContainer viene configurato con il container di default (senza nome). Infine, viene creata l’istanza del ServiceHost passando lo unityContainer.

A questo punto specifichiamo nel file .svc l’utilizzo dello UnityServiceHostFactory:

  1: <%@ ServiceHost Language="C#" Debug="true" 
  2: Service="DotNetSide.WCF.IoC.Service.BookService, DotNetSide.WCF.IoC.Service"
  3: Factory="DotNetSide.WCF.IoC.Unity.UnityServiceHostFactory, DotNetSide.WCF.IoC.Unity" %>

Ora siamo pronti per eseguire la nostra applicazione. In allegato troverete il codice completo dell’esempio.

Anche qui il codice è reso volutamente molto semplice per evitare di essere troppo prolisso.

bye Smile

Posted: Mar 22 2009, 05:20 AM by Fabio.Cozzolino | with 1 comment(s)
Filed under: ,
Inversion of Control con WCF e Unity

Nei giorni scorsi mi è capitato spesse volte di parlare con amici e colleghi di Inversion of Control (IoC) e WCF. Perciò mi sono deciso a pubblicare un breve post per spiegare i passaggi necessari per ottenere l’utilizzo di IoC con un servizio WCF. Nel caso specifico ho scelto Unity come framework per l’IoC.

Sono innanzitutto necessari 3 componenti:

  • InstanceProvider: è il componente che si incarica di creare l’istanza del servizio. In definitiva è quello che userà direttamente Unity;
  • ServiceBehavior: ci consente di creare l’istanza dell’InstanceProvider e di “agganciarla” al servizio corrente;
  • ServiceHost: è il gestore del nostro servizio. Il ServiceHost ha il compito di configurare il servizio per l’utilizzo e quindi si occuperà di applicare il ServiceBehavior creato;

Avremo quindi rispettivamente: UnityInstanceProvider, UnityServiceBehavior e UnityServiceHost.

UnityInstanceProvider

Il primo passo è, come detto, quello di creare l’InstanceProvider. Il codice è in realtà molto semplice, almeno in questa prima fase:

  1: internal class UnityInstanceProvider : IInstanceProvider
  2: {
  3:     private readonly IUnityContainer container;
  4:     private readonly Type contractType;
  5: 
  6:     public UnityInstanceProvider(IUnityContainer container, Type contractType)
  7:     {
  8:         this.container = container;
  9:         this.contractType = contractType;
 10:     }
 11: 
 12:     public object GetInstance(InstanceContext instanceContext)
 13:     {
 14:         return GetInstance(instanceContext, null);
 15:     }
 16: 
 17:     public object GetInstance(InstanceContext instanceContext, Message message)
 18:     {
 19:         return container.Resolve(contractType);
 20:     }
 21: 
 22:     public void ReleaseInstance(InstanceContext instanceContext, object instance)
 23:     {
 24:         container.Teardown(instance);
 25:     }
 26: }

Il costruttore accetta in input l’istanza del container ed il tipo di contratto dello specifico endpoint. Entrambi verranno poi utilizzati dal GetInstance per risolvere l’istanza sulla base del contesto. Il metodo può chiaramente essere migliorato.

UnityServiceBehavior

Il ServiceBehavior, come detto, si occupa di creare l’InstanceProvider per gli specifici endpoint del servizio:

  1: public class UnityServiceBehavior : IServiceBehavior
  2: {
  3:     private readonly IUnityContainer container;
  4: 
  5:     public UnityServiceBehavior(IUnityContainer container)
  6:     {
  7:         this.container = container;
  8:     }
  9: 
 10:     public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
 11:     {
 12:     }
 13: 
 14:     public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
 15:     {
 16:     }
 17: 
 18:     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
 19:     {
 20:         foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
 21:         {
 22:             foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
 23:             {
 24:                 if (endpointDispatcher.ContractName != "IMetadataExchange")
 25:                 {
 26:                     string contractName = endpointDispatcher.ContractName;
 27:                     ServiceEndpoint serviceEndpoint = serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName);
 28:                     endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(this.container, serviceEndpoint.Contract.ContractType);
 29:                 }
 30:             }
 31:         }
 32:     }
 33: }

Il costruttore riceve dal ServiceHost l’istanza del container che viene poi assegnata al DispatchRuntime dell’EndpointDispatcher, selezionando anche il tipo di contratto che deve essere utilizzato per la risoluzione dell’istanza del servizio.

UnityServiceHost

Il passo finale è la creazione del ServiceHost, il componente che ci consente di configurare il servizio:

  1: public class UnityServiceHost : ServiceHost
  2: {
  3:     private IUnityContainer unityContainer;
  4: 
  5:     public UnityServiceHost(IUnityContainer unityContainer, Type serviceType) : base(serviceType)
  6:     {
  7:         this.unityContainer = unityContainer;
  8:     }
  9: 
 10:     protected override void OnOpening()
 11:     {
 12:         base.OnOpening();
 13: 
 14:         if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null)
 15:         {
 16:             this.Description.Behaviors.Add(new UnityServiceBehavior(this.unityContainer));
 17:         }
 18:     }
 19: }

Anche qui l’implementazione è davvero molto semplice. Il ServiceHost riceve nel costruttore l’istanza del container e contemporaneamente il tipo che identifica il servizio. Nell’override del metodo OnOpening, eseguito prima dell’apertura dei channels, il servicehost si occupa di verificare l’esistenza dell’UnityServiceBehavior e, se non trovato, lo istanzia passando a sua volta l’istanza del container.

Utilizzo in una applicazione console self-hosted

Ora siamo pronti per provare. Questa è la configurazione di esempio che utilizzeremo per il nostro servizio:

  1: <?xml version="1.0" encoding="utf-8" ?>
  2: <configuration>
  3:   <configSections>
  4:     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  5:   </configSections>
  6:   
  7:   <unity>
  8: 
  9:     <containers>
 10: 
 11:       <container>
 12:         <types>
 13:           
 14:           <type type="DotNetSide.WCF.IoC.Console.InnerBookService, DotNetSide.WCF.IoC.Console"
 15:                 name="inner"/>
 16: 
 17:           <type type="DotNetSide.WCF.IoC.Console.IBookService, DotNetSide.WCF.IoC.Console"
 18:                 mapTo="DotNetSide.WCF.IoC.Console.BookService, DotNetSide.WCF.IoC.Console">
 19:             <typeConfig>
 20:               <constructor>
 21:                 <param name="innerService" parameterType="DotNetSide.WCF.IoC.Console.InnerBookService, DotNetSide.WCF.IoC.Console">
 22:                   <dependency name="inner" />
 23:                 </param>
 24:               </constructor>
 25:             </typeConfig>
 26:           </type>
 27: 
 28:         </types>
 29:       </container>
 30: 
 31:     </containers>
 32:     
 33:   </unity>
 34: 
 35: </configuration>

Molto semplicemente deve essere creata un’istanza dell’InnerBookService e passata come parametro nel costruttore del nostro servizio BookService, implementazione del nostro contratto IBookService:

  1: [ServiceContract]
  2: internal interface IBookService
  3: {
  4:     [OperationContract]
  5:     Book ReadBook(string bookId);
  6: }
  7: 
  8: class BookService : IBookService
  9: {
 10:     private readonly InnerBookService innerService;
 11: 
 12:     public BookService(InnerBookService innerService)
 13:     {
 14:         this.innerService = innerService;
 15:     }
 16: 
 17:     public Book ReadBook(string bookId)
 18:     {
 19:         return this.innerService.ReadBook(bookId);
 20:     }
 21: }
 22: 
 23: class InnerBookService
 24: {
 25:     public Book ReadBook(string bookId)
 26:     {
 27:         return new Book()
 28:         {
 29:             Title = "WCF",
 30:             Description = "A book on Windows Communication Foundation"
 31:         };
 32:     }
 33: }

Costruiamo quindi l’istanza del ServiceHost passando il container UnityContainer:

  1: var unityContainer = new UnityContainer();
  2: var configurationSection = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
  3: configurationSection.Containers.Default.Configure(unityContainer);
  4: 
  5: Uri serviceAddress = new Uri("http://localhost:9001/BookService");
  6: Uri mexAddress = new Uri("http://localhost:9001/BookService/mex");
  7: using (UnityServiceHost host = new UnityServiceHost(unityContainer, unityContainer.Resolve<IBookService>().GetType()))
  8: {
  9:     host.Description.Behaviors.Add(new ServiceMetadataBehavior());
 10:     host.AddServiceEndpoint(typeof(IBookService), new BasicHttpBinding(), serviceAddress);
 11:     host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), mexAddress);
 12: 
 13:     host.Open();
 14: 
 15:     System.Console.Read();
 16: 
 17:     host.Close();
 18: }

Abbiamo anche aggiunto un endpoint di tipo WS-Metadata Exchange, per la creazione del quale abbiamo anche evitato di utilizzare l’IoC nel UnityServiceBehavior, così possiamo anche creare il nostro client e testare il tutto.

Davvero molto semplice, non credete ?? Big Smile

Nei prossimi post aggiungerò qualche tassello per rendere più completo il discorso, nel frattempo aspetto i vostri feedback.

bye

Posted: Mar 21 2009, 08:37 PM by Fabio.Cozzolino | with 2 comment(s)
Filed under: ,
Articolo su ioProgrammo n° 137

Su ioProgrammo di Aprile è stato pubblicato un mio articolo che descrive come utilizzare Workflow Foundation per gestire uno scheduler completamente personalizzato ma soprattutto facilmente estendendibile.

Magari, se lo leggete, fatemi sapere che ne pensate ... Big Smile

Windows 7 Installation Fest SOLD OUT

Sarà forse l'attesa del nuovo sistema operativo, sarà forse la curiosità che c'è dietro, sarà forse la primavera, fatto sta che l'installation fest del 26 Marzo a Bari è già SOLD OUT. Tutti i posti sono prenotati Big Smile.

Se però già sapete di non poter partecipare, vi chiedo di liberare il posto già prenotato così da consentire la partecipazione a chi è in attesa.

Grazie, ci vediamo il 26!!!

Posted: Mar 15 2009, 06:04 PM by Fabio.Cozzolino | with no comments
Filed under:
Articolo su Workflow Foundation e le chiamate sincrone

Ho da poco pubblicato un articolo su come invocare workflow in modalità sincrona. Leggetelo e magari mi fate sapere che ne pensate Big Smile...

Posted: Mar 12 2009, 12:48 AM by Fabio.Cozzolino | with no comments
Filed under: ,
[WCF REST#1] Implementazione di un semplice servizio RESTful

Introduzione

Ormai diverse settimane fa abbiamo parlato di cosa è REST. Oggi vediamo come sviluppare un primo, semplice servizio con WCF.

Il contratto di un servizio, come ormai sappiamo, in WCF viene tradotto con la definizione di una interfaccia marcata con gli attributi ServiceContract ed OperationContract:

  1: [ServiceContract(Namespace = "urn:MyBookNamespace")]
  2: public interface IBookService
  3: {
  4:     [OperationContract]
  5:     Book ReadBook(string bookId);
  6: }

L'implementazione dell'interfaccia può essere quindi simile a questa:

  1: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  2: public class BookService : IBookService
  3: {
  4:     public Book ReadBook(string bookId)
  5:     {
  6:         return BookDB.Read(bookId);
  7:     }
  8: }

Notate l'attributo [WebGet]? L'attributo ci consente di definire il metodo per la ricezione di richieste con il verbo GET HTTP.

Il behavior WebHttpBehavior

Da solo, però, in realtà non ha alcun effetto sul servizio. Dobbiamo definire l'utilizzo del behavior EnableWebScript:

  1: <endpointBehaviors>
  2:   <behavior name="BookService_RESTBehavior">
  3:     <enableWebScript/>
  4:   </behavior>
  5: </endpointBehaviors>

Il behavior WebScriptEnablingBehavior si occupa di esporre il servizio attraverso degli script javascript per abilitare la creazione di proxy client da pagine web. Vedremo infatti la creazione di un endpoint costituito dall'indirizzo del servizio più il suffisso /js. Nel nostro caso il servizio produrrà un js simile a questo:

image

Definiamo il binding

Per completare il nostro servizio, definiamo il binding da utilizzare. Con il .NET Framework 3.5 è stato introdotto il WebHttpBinding:

  1: <bindings>
  2:   <webHttpBinding>
  3:     <binding name="BookServiceWebBinding">
  4:       <security mode="None"/>
  5:     </binding>
  6:   </webHttpBinding>
  7: </bindings>

Si tratta di un binding che funziona esclusivamente con il protocollo http, come è facile intuire, e si occupa principalmente di configurare il trasporto (HttpTransportBindingElement) per il ManualAddressing a true e la versione del messaggio (MessageVersion) su None per il WebMessageEncodingBindingElement. Questo consente di non formattare il messaggio utilizzando SOAP.

Configurazione del servizio

Vediamo ora la configurazione dell'endpoint del nostro servizio ospitato su IIS:

  1: <services>
  2:   <service name="BookService" 
  3:            behaviorConfiguration="BookServiceBehavior">
  4:     <endpoint address="" 
  5:               binding="webHttpBinding" 
  6:               contract="IBookService"
  7:               behaviorConfiguration="BookService_RESTBehavior"
  8:               bindingConfiguration="BookServiceWebBinding"/>
  9:   </service>
 10: </services>

Il servizio così configurato è pronto per l'utilizzo da parte del client.

Il web client

Per utilizzare il servizio direttamente da una pagina web ASP.NET è sufficiente inserire un riferimento all'svc utilizzando il ServiceReference del controllo ScriptManager:

  1: <asp:ScriptManager ID="sm1" runat="server">
  2:     <Services>
  3:         <asp:ServiceReference Path="~/BookService.svc" />
  4:     </Services>
  5: </asp:ScriptManager>

Infine creiamo il nostro script che richiama il servizio. Ad esempio:

  1: function GetBook(bookId) {
  2:     var proxy = new MyBookNamespace.IBookService();
  3:     proxy.ReadBook(
  4:         bookId,
  5:         GetBook_OnSuccess,
  6:         GetBook_OnError,
  7:         null);
  8: }
  9: function GetBook_OnSuccess(result) {
 10:     alert("Titolo: " + result.Title + 
 11:         "\r\nDescrizione: " + result.Description);
 12: }
 13: function GetBook_OnError(result) {
 14:     alert("Error: " + result.Message);
 15: }

Possiamo quindi richiamare la funzione GetBook da qualsiasi punto della pagina. Semplice vero? Big Smile

Un ultima nota. Il namespace di esempio MyBookNamespace dichiarato nel contratto IBookService, viene letto ed utilizzato dal client, come potete vedere dalla riga 2.

Request/Response formats

I messaggi scambiati in questa modalità sono tutti in formato JSON (JavaScript Object Notation) un formato testuale per la rappresentazione dei dati molto semplice e fortemente integrato in javascript.

Analizziamo i messaggi con il Web Development Helper di Nikhil Kotari:

image

Oltre ai messaggi in formato JSON, notiamo nel titolo l'URL del servizio che viene invocato: http://localhost/RESTSimpleService/BookService.svc/ReadBook. ReadBook è semplicemente il nome del metodo che viene invocato in GET unito all'indirizzo base del servizio.

Conclusione

In questo post/articolo abbiamo visto come creare un semplice servizio RESTful per poi consumarlo in una pagina web utilizzando ASP.NET Ajax e javascript. Nei prossimi post mostrerò come utilizzare REST in maniera più approfondita e dettagliata, sfruttando tutti i verbi http per interrogare e modificare una risorsa web.

Posted: Mar 05 2009, 12:29 AM by Fabio.Cozzolino | with no comments
Filed under: ,