Supporto di memorizzazione nella cache per servizi HTTP Web WCFCaching Support for WCF Web HTTP Services

.NET Framework 4.6.1.NET Framework 4.6.1 Consente di utilizzare il meccanismo dichiarativo di memorizzazione nella cache già disponibile in ASP.NET nei servizi HTTP Web WCF. enables you to use the declarative caching mechanism already available in ASP.NET in your WCF Web HTTP services. In questo modo è possibile memorizzare nella cache le risposte inviate dalle operazioni del servizio HTTP Web WCF.This allows you to cache responses from your WCF Web HTTP service operations. Se un utente invia un'operazione HTTP GET al servizio configurato per la memorizzazione nella cache, ASP.NET restituisce la risposta memorizzata nella cache e il metodo del servizio non viene chiamato.When a user sends an HTTP GET to your service that is configured for caching, ASP.NET sends back the cached response and the service method is not called. Se la cache scade, al successivo tentativo di invio di un'operazione HTTP GET da parte dell'utente, viene chiamato il metodo del servizio e la risposta viene nuovamente memorizzata nella cache.When the cache expires, the next time a user sends an HTTP GET, your service method is called and the response is once again cached. Per ulteriori informazioni sulla memorizzazione nella cache di ASP.NET, vedere Cenni preliminari sulla memorizzazione nella cache di ASP.NETFor more information about ASP.NET caching, see ASP.NET Caching Overview

Memorizzazione nella cache del servizio HTTP Web di baseBasic Web HTTP Service Caching

Per abilitare la memorizzazione nella cache del servizio HTTP WEB, è innanzitutto necessario abilitare la compatibilità ASP.NET applicando AspNetCompatibilityRequirementsAttribute al servizio, impostando RequirementsMode su Allowed o Required.To enable WEB HTTP service caching you must first enable ASP.NET compatibility by applying the AspNetCompatibilityRequirementsAttribute to the service setting RequirementsMode to Allowed or Required.

.NET Framework 4.NET Framework 4 introduce un nuovo attributo denominato AspNetCacheProfileAttribute che consente di specificare un nome di profilo cache. introduces a new attribute called AspNetCacheProfileAttribute that allows you to specify a cache profile name. L'attributo è applicato a un'operazione del servizio.This attribute is applied to a service operation. Nell'esempio seguente AspNetCompatibilityRequirementsAttribute viene applicato a un servizio per abilitare la compatibilità ASP.NET e l'operazione GetCustomer viene configurata per la memorizzazione nella cache.The following example applies the AspNetCompatibilityRequirementsAttribute to a service to enable ASP.NET compatibility and configures the GetCustomer operation for caching. Il System.ServiceModel.Activation.AspNetCacheProfileAttribute attributo specifica un profilo della cache che contiene le impostazioni della cache da utilizzare.The System.ServiceModel.Activation.AspNetCacheProfileAttribute attribute specifies a cache profile that contains the cache settings to be used.

[ServiceContract] 
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class Service
{
    [WebGet(UriTemplate = "{id}")]
    [AspNetCacheProfile("CacheFor60Seconds")]
    public Customer GetCustomer(string id)
    {
        // ...
    }
}

È inoltre necessario abilitare la modalità di compatibilità ASP.NET nel file Web.config, come indicato nell'esempio seguente.You must also turn on ASP.NET compatibility mode in the Web.config file as shown in the following example.

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>

Avviso

Se la modalità di compatibilità ASP.NET non è abilitata e viene utilizzato AspNetCacheProfileAttribute, verrà generata un'eccezione.If ASP.NET compatibility mode is not turned on and the AspNetCacheProfileAttribute is used an exception is thrown.

Il nome di profilo cache specificato da AspNetCacheProfileAttribute identifica un profilo cache aggiunto al file di configurazione Web.config.The cache profile name specified by the AspNetCacheProfileAttribute identifies a cache profile that is added to your Web.config configuration file. Il profilo della cache viene definito con un <outputCacheSetting> come illustrato nell'esempio di configurazione seguente.The cache profile is defined with in a <outputCacheSetting> element as shown in the following configuration example.

<!-- ...  -->
<system.web>  
   <caching>  
      <outputCacheSettings>  
         <outputCacheProfiles>  
            <add name="CacheFor60Seconds" duration="60" varyByParam="none" sqlDependency="MyTestDatabase:MyTable"/>  
         </outputCacheProfiles>  
      </outputCacheSettings>  
   </caching>  
   <!-- ... -->  
</system.web>  

Si tratta dello stesso elemento di configurazione disponibile per le applicazioni ASP.NET.This is the same configuration element that is available to ASP.NET applications. Per ulteriori informazioni sui profili cache ASP.NET, vedere OutputCacheProfile.For more information about ASP.NET cache profiles, see OutputCacheProfile. Per i servizi HTTP Web, gli attributi più importanti del profilo cache sono cacheDuration e varyByParam.For Web HTTP services, the most important attributes in the cache profile are: cacheDuration and varyByParam. Entrambi gli attributi sono obbligatori.Both of these attributes are required. cacheDuration imposta la quantità di tempo in secondi necessaria per la memorizzazione nella cache di una risposta.cacheDuration sets the amount of time a response should be cached in seconds. varyByParam consente di specificare un parametro della stringa di query utilizzato per memorizzare risposte nella cache.varyByParam allows you to specify a query string parameter that is used to cache responses. Tutte le richieste effettuate con valori del parametro della stringa di query diversi vengono memorizzate nella cache separatamente.All requests made with different query string parameter values are cached separately. Ad esempio, una volta effettuata una richiesta iniziale a http://MyServer/MyHttpService/MyOperation?param=10 tutte le richieste successive effettuate con lo stesso URI verrebbe restituite la risposta memorizzata nella cache (purché non sia trascorsa la durata della cache).For example, once an initial request is made to http://MyServer/MyHttpService/MyOperation?param=10 all subsequent requests made with the same URI would be returned the cached response (so long as the cache duration has not elapsed). Le risposte per una richiesta analoga ma con valore diverso per quanto riguarda il parametro della stringa di query vengono memorizzate nella cache separatamente.Responses for a similar request that is the same but has a different value for the parameter query string parameter are cached separately. Se non si desidera questo tipo di comportamento di memorizzazione nella cache, impostare varyByParam su "none".If you do not want this separate caching behavior, set varyByParam to "none".

Dipendenza dalla cache SQLSQL Cache Dependency

È inoltre possibile memorizzare nella cache le risposte di un servizio HTTP Web con una dipendenza della cache SQL.Web HTTP service responses can also be cached with a SQL cache dependency. Se il servizio HTTP Web WCF dipende da dati archiviati in un database SQL, potrebbe risultare opportuno memorizzare nella cache la risposta del servizio e invalidare la risposta memorizzata nella cache quando i dati nella tabella del database SQL vengono modificati.If your WCF Web HTTP service depends on data stored in a SQL database, you may want to cache the service's response and invalidate the cached response when data in the SQL database table changes. Questo comportamento viene completamente configurato all'interno del file Web.config.This behavior is configured completely within the Web.config file. È necessario definire una stringa di connessione nel <connectionStrings> elemento.You must first define a connection string in the <connectionStrings> element.

<connectionStrings>
  <add name="connectString"
       connectionString="Data Source=MyService;Initial Catalog=MyTestDatabase;Integrated Security=True"
       providerName="System.Data.SqlClient" />
</connectionStrings>

Quindi è necessario abilitare la dipendenza della cache SQL all'interno di un <caching> elemento all'interno di <system.web> come illustrato nell'esempio di configurazione seguente.Then you must enable SQL cache dependency within a <caching> element within the <system.web> element as shown in the following config example.

<system.web>
  <caching>
    <sqlCacheDependency enabled="true" pollTime="1000">
      <databases>
        <add name="MyTestDatabase" connectionStringName="connectString" />
      </databases>
    </sqlCacheDependency>
    <!-- ... -->
  </caching>
  <!-- ... -->
</system.web>

In questo caso viene abilitata la dipendenza della cache SQL e viene impostato un tempo di polling di 1000 millisecondi.Here SQL cache dependency is enabled and a polling time of 1000 milliseconds is set. Ogni volta che scade il tempo di polling, viene verificata la presenza di aggiornamenti nella tabella di database.Each time the polling time elapses the database table is checked for updates. Se vengono rilevate modifiche, il contenuto della cache viene rimosso e, la volta successiva in cui l'operazione del servizio viene richiamata, viene memorizzata nella cache una nuova risposta.If changes are detected the contents of the cache are removed and the next time the service operation is invoked a new response is cached. All'interno di <sqlCacheDependency> elemento aggiungere i database e fare riferimento alle stringhe di connessione all'interno di <databases> come illustrato nell'esempio seguente.Within the <sqlCacheDependency> element add the databases and reference the connection strings within the <databases> element as shown in the following example.

<system.web>
  <caching>
    <sqlCacheDependency enabled="true" pollTime="1000">
      <databases>
        <add name="MyTestDatabase" connectionStringName="connectString" />
      </databases>  
    </sqlCacheDependency>  
    <!-- ... -->  
  </caching>  
  <!-- ... -->  
</system.web>  

Successivamente è necessario configurare le impostazioni della cache di output all'interno di <caching> come illustrato nell'esempio seguente.Next you must configure the output cache settings within the <caching> element as shown in the following example.

<system.web>
  <caching>  
    <!-- ...  -->
    <outputCacheSettings>
      <outputCacheProfiles>
        <add name="CacheFor60Seconds" duration="60" varyByParam="none" sqlDependency="MyTestDatabase:MyTable" />
      </outputCacheProfiles>
    </outputCacheSettings>
  </caching>
  <!-- ... -->
</system.web>

In questo caso la durata della cache è impostata su 60 secondi, varyByParam è impostato su none e sqlDependency è impostato su un elenco con valori delimitati da punti e virgola di coppie di nomi/tabelle del database separate dai due punti.Here the cache duration is set to 60 seconds, varyByParam is set to none and sqlDependency is set to a semicolon delimited list of database name/table pairs separated by colons. Se i dati in MyTable vengono modificati, la risposta memorizzata nella cache per l'operazione del servizio viene rimossa e, se si richiama l'operazione, una nuova risposta viene generata, memorizzata nella cache e restituita al client.When data in MyTable is changed the cached response for the service operation is removed and when the operation is invoked a new response is generated (by calling the service operation), cached, and returned to the client.

Importante

Per accedere a un database SQL con ASP.NET, è necessario usare il strumento di registrazione di SQL Server ASP.NET.For ASP.NET to access a SQL database, you must use the ASP.NET SQL Server Registration Tool. È inoltre necessario consentire l'accesso dell'account utente appropriato al database e alla tabella.In addition you must allow the appropriate user account access to the database and table. Per altre informazioni, vedere accesso a SQL Server da un'applicazione Web.For more information, see Accessing SQL Server from a Web Application.

Memorizzazione nella cache basata su HTTP GET condizionaleConditional HTTP GET Based Caching

In scenari HTTP Web HTTP GET condizionale viene spesso utilizzato dai servizi per implementare la memorizzazione nella cache di intelligente HTTP come descritto nella specifica HTTP.In Web HTTP scenarios a conditional HTTP GET is often used by services to implement intelligent HTTP caching as described in the HTTP Specification. A tale scopo, il servizio deve impostare il valore dell'intestazione ETag nella risposta HTTP.To do this the service must set the value of the ETag header in the HTTP response. Deve inoltre verificare l'intestazione If-None-Match nella richiesta HTTP per controllare se una o più delle intestazioni ETag specificate corrisponde all'intestazione ETag corrente.It also must check the If-None-Match header in the HTTP request to see whether any of the ETag specified matches the current ETag.

Per le richieste GET e HEAD, CheckConditionalRetrieve utilizza un valore ETag e lo verifica rispetto all'intestazione If-None-Match della richiesta.For GET and HEAD requests, CheckConditionalRetrieve takes an ETag value and checks it against the If-None-Match header of the request. Se l'intestazione è presente e viene individuata una corrispondenza, viene generata un'eccezione WebFaultException con codice di stato HTTP 304 (non modificato) e viene aggiunta un'intestazione ETag alla risposta con l'intestazione ETag corrispondente.If the header is present and there is a match, a WebFaultException with a HTTP status code 304 (Not Modified) is thrown and an ETag header is added to the response with the matching ETag.

Un overload del metodo CheckConditionalRetrieve utilizza la data di un'ultima modifica e la controlla rispetto all'intestazione If-Modified-Since della richiesta.One overload of the CheckConditionalRetrieve method takes a last modified date and checks it against the If-Modified-Since header of the request. Se l'intestazione è presente e la risorsa non è stata ancora modificata, viene generata un'eccezione WebFaultException con codice di stato HTTP 304 (non modificato).If the header is present and the resource has not been modified since, a WebFaultException with an HTTP status code 304 (Not Modified) is thrown.

Per le richieste PUT, POST e DELETE, CheckConditionalUpdate utilizza il valore ETag corrente di una risorsa.For PUT, POST, and DELETE requests, CheckConditionalUpdate takes the current ETag value of a resource. Se il valore ETag corrente è null, il metodo verifica che l'intestazione If-None-Match ha il valore "*".If the current ETag value is null, the method checks that the If-None- Match header has a value of "*". Se il valore ETag corrente non è un valore predefinito, il metodo controlla il valore ETag corrente rispetto all'intestazione If- Match della richiesta.If the current ETag value is not a default value, then the method checks the current ETag value against the If- Match header of the request. In entrambi i casi, il metodo genera un'eccezione WebFaultException con codice di stato HTTP 412 (precondizione non riuscita) se l'intestazione prevista non è presente nella richiesta o il relativo valore non soddisfa il controllo condizionale e imposta l'intestazione ETag della risposta sul valore ETag corrente.In either case, the method throws a WebFaultException with an HTTP status code 412 (Precondition Failed) if the expected header is not present in the request or its value does not satisfy the conditional check and sets the ETag header of the response to the current ETag value.

Entrambi i metodi CheckConditional e il metodo SetETag verificano che il valore ETag impostato nell'intestazione della risposta sia valido in base alla specifica HTTP.Both the CheckConditional methods and the SetETag method ensures that the ETag value set on the response header is a valid ETag according to the HTTP specification. Ciò include la possibilità di racchiudere il valore ETag tra virgolette, se non già presenti, e di utilizzare i caratteri di escape per eventuali virgolette interne.This includes surrounding the ETag value in double quotes if they are not already present and properly escaping any internal double quote characters. Il confronto ETag debole non è supportato.Weak ETag comparison is not supported.

Nell'esempio seguente viene illustrato come utilizzare i metodi.The following example shows how to use these methods.

[WebGet(UriTemplate = "{id}"), Description("Returns the specified customer from customers collection. Returns NotFound if there is no such customer. Supports conditional GET.")]
public Customer GetCustomer(string id)
{
    lock (writeLock)
    {
        // return NotFound if there is no item with the specified id.
        object itemEtag = customerEtags[id];
        if (itemEtag == null)
        {
            throw new WebFaultException(HttpStatusCode.NotFound);
        }

        // return NotModified if the client did a conditional GET and the customer item has not changed
        // since when the client last retrieved it
        WebOperationContext.Current.IncomingRequest.CheckConditionalRetrieve((long)itemEtag);
        Customer result = this.customers[id] as Customer;

        // set the customer etag before returning the result
        WebOperationContext.Current.OutgoingResponse.SetETag((long)itemEtag);
        return result;
    }
}

Considerazioni sulla sicurezzaSecurity Considerations

Le risposte a richieste che richiedono autorizzazione non devono essere memorizzate nella cache, perché l'autorizzazione non viene effettuata quando la risposta viene servita dalla cache.Requests that require authorization should not have their responses cached, because the authorization is not performed when the response is served from the cache. La memorizzazione nella cache di tali risposte introdurrebbe una grave vulnerabilità per la sicurezza.Caching such responses would introduce a serious security vulnerability. In genere, le richiede che richiedono autorizzazione forniscono dati specifici per gli utenti, pertanto la memorizzazione nella cache sul lato server non è vantaggiosa.Usually, requests that require authorization provide user-specific data and therefore server-side caching is not even beneficial. In tali situazioni, risulta più appropriata la memorizzazione nella cache sul lato client o, semplicemente, non eseguire alcuna memorizzazione nella cache.In such situations, client-side caching or simply not caching at all will be more appropriate.