Cacheunterstützung für WCF-Web-HTTP-DiensteCaching Support for WCF Web HTTP Services

.NET Framework 4.6.1.NET Framework 4.6.1 ermöglicht es Ihnen, verwenden Sie deklarative Zwischenspeichermechanismus in ASP.NET in Ihre WCF-Web-HTTP-Dienste bereits verfügbar. enables you to use the declarative caching mechanism already available in ASP.NET in your WCF Web HTTP services. Auf diese Weise können Sie Antworten der WCF-Web-HTTP-Dienstvorgänge zwischenspeichern.This allows you to cache responses from your WCF Web HTTP service operations. Wenn ein Benutzer HTTP GET an den Dienst sendet, der zum Zwischenspeichern konfiguriert ist, sendet ASP.NET die zwischengespeicherte Antwort zurück, und die Dienstmethode wird nicht aufgerufen.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. Wenn der Cache abgelaufen ist, wird beim nächsten Senden eines HTTP GET durch einen Benutzer die Dienstmethode aufgerufen und die Antwort erneut zwischengespeichert.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. Weitere Informationen zur Zwischenspeicherung in ASP.NET finden Sie unter Übersicht über das Zwischenspeichern von ASP.NETFor more information about ASP.NET caching, see ASP.NET Caching Overview

Grundlegendes Zwischenspeichern von Web-HTTP-DienstenBasic Web HTTP Service Caching

Zum Aktivieren des Zwischenspeicherns von WEB-HTTP-Diensten müssen Sie zuerst die ASP.NET-Kompatibilität aktivieren, indem Sie AspNetCompatibilityRequirementsAttribute auf die Diensteinstellung RequirementsMode und Allowed oder Required anwenden.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.

Mit .NET Framework 4.NET Framework 4 wird ein neues Attribut mit dem Namen AspNetCacheProfileAttribute eingeführt, das Ihnen das Angeben eines Cacheprofilnamens ermöglicht..NET Framework 4.NET Framework 4 introduces a new attribute called AspNetCacheProfileAttribute that allows you to specify a cache profile name. Dieses Attribut wird auf einen Dienstvorgang angewendet.This attribute is applied to a service operation. Im folgenden Beispiel wird AspNetCompatibilityRequirementsAttribute auf einen Dienst angewendet, um ASP.NET-Kompatibilität zu erzielen, und der GetCustomer-Vorgang wird für die Zwischenspeicherung konfiguriert.The following example applies the AspNetCompatibilityRequirementsAttribute to a service to enable ASP.NET compatibility and configures the GetCustomer operation for caching. Die System.ServiceModel.Activation.AspNetCacheProfileAttribute Attribut gibt ein Cacheprofil, das die Einstellungen zum Zwischenspeichern zu verwendende enthält.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)
    {
        // ...
    }
}

Sie müssen auch den ASP.NET-Kompatibilitätsmodus in der Datei "Web.config" aktivieren, wie im folgenden Beispiel gezeigt.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>

Warnung

Wenn der ASP.NET-Kompatibilitätsmodus nicht aktiviert ist und AspNetCacheProfileAttribute verwendet wird, wird eine Ausnahme ausgelöst.If ASP.NET compatibility mode is not turned on and the AspNetCacheProfileAttribute is used an exception is thrown.

Der von AspNetCacheProfileAttribute angegebene Cacheprofilname identifiziert ein Cacheprofil, das der Konfigurationsdatei "Web.config" hinzugefügt wird.The cache profile name specified by the AspNetCacheProfileAttribute identifies a cache profile that is added to your Web.config configuration file. Das Cacheprofil mit definiert ist, einem <outputCacheSetting>-Element wie im folgenden Konfigurationsbeispiel gezeigt.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>  

Dies ist das gleiche Konfigurationselement, das für ASP.NET-Anwendungen verfügbar ist.This is the same configuration element that is available to ASP.NET applications. Weitere Informationen zu ASP.NET-Cacheprofilen finden Sie unter OutputCacheProfile.For more information about ASP.NET cache profiles, see OutputCacheProfile. Die wichtigsten Attribute im Cacheprofil für Web-HTTP-Dienste sind cacheDuration und varyByParam.For Web HTTP services, the most important attributes in the cache profile are: cacheDuration and varyByParam. Beide Attribute sind erforderlich.Both of these attributes are required. cacheDuration legt den Zeitraum in Sekunden fest, für den eine Antwort zwischengespeichert werden soll.cacheDuration sets the amount of time a response should be cached in seconds. Mit varyByParam können Sie einen Abfragezeichenfolgenparameter angeben, der zum Zwischenspeichern von Antworten verwendet wird.varyByParam allows you to specify a query string parameter that is used to cache responses. Alle Anforderungen, die mit unterschiedlichen Abfragezeichenfolgenparameter-Werten gestellt werden, werden separat zwischengespeichert.All requests made with different query string parameter values are cached separately. Nachdem eine ursprüngliche Anforderung an erfolgt ist beispielsweise http://MyServer/MyHttpService/MyOperation?param=10 alle nachfolgende Anforderungen mit der gleichen URI zurückgegeben werden würde die zwischengespeicherte Antwort (sofern die Cachedauer nicht verstrichen ist).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). Antworten für eine ähnliche Anforderung, die gleich ist, jedoch über einen anderen Wert als Abfragezeichenfolgenparameter verfügt, werden getrennt zwischengespeichert.Responses for a similar request that is the same but has a different value for the parameter query string parameter are cached separately. Falls Sie dieses separate Zwischenspeicherverhalten nicht wünschen, legen Sie varyByParam auf "none" fest.If you do not want this separate caching behavior, set varyByParam to "none".

SQL-CacheabhängigkeitSQL Cache Dependency

Antworten auf Web-HTTP-Dienste können auch mit einer SQL-Cacheabhängigkeit zwischengespeichert werden.Web HTTP service responses can also be cached with a SQL cache dependency. Wenn der WCF-Web-HTTP-Dienst von in einer SQL-Datenbank gespeicherten Daten abhängig ist, sollten Sie die Antwort des Diensts zwischenspeichern und die zwischengespeicherte Antwort für ungültig erklären, wenn sich die Daten in der SQL-Datenbanktabelle ändern.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. Dieses Verhalten wird vollständig in der Datei "Web.config" konfiguriert.This behavior is configured completely within the Web.config file. Definieren Sie zunächst eine Verbindungszeichenfolge in der <connectionStrings> Element.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>

Dann müssen Sie die SQL-Cacheabhängigkeit innerhalb Aktivieren einer <caching> Element innerhalb der <system.web> Element wie im folgenden Beispiel Config dargestellt.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>

Hier wird die SQL-Cacheabhängigkeit aktiviert und ein Abrufzeitraum von 1000 Millisekunden festgelegt.Here SQL cache dependency is enabled and a polling time of 1000 milliseconds is set. Wenn der Abrufzeitraum verstrichen ist, wird die Datenbanktabelle jeweils auf Updates geprüft.Each time the polling time elapses the database table is checked for updates. Wenn Änderungen erkannt werden, wird der Inhalt des Caches entfernt, und beim nächsten Aufrufen des Dienstvorgangs wird eine neue Antwort zwischengespeichert.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. In der <sqlCacheDependency> Element Datenbanken hinzuzufügen, und verweisen Sie die Verbindungszeichenfolgen in der <databases>-Element wie im folgenden Beispiel gezeigt.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>  

Als Nächstes müssen Sie konfigurieren die ausgabechacheinstellungen innerhalb der <caching>-Element wie im folgenden Beispiel gezeigt.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>

Hier wird die Cachedauer auf 60 Sekunden festgelegt, varyByParam wird auf "none" festgelegt, und sqlDependency wird auf eine durch Semikolons getrennte Liste mit Datenbankname/Tabelle-Paaren festgelegt, die jeweils durch Doppelpunkte getrennt sind.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. Falls Daten in MyTable geändert werden, wird die zwischengespeicherte Antwort für den Dienstvorgang entfernt. Wenn der Vorgang dann aufgerufen wird, wird eine neue Antwort generiert (durch das Aufrufen des Dienstvorgangs), zwischengespeichert und für den Client zurückgegeben.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.

Wichtig

Verwenden Sie für ASP.NET für den Zugriff auf eine SQL­Datenbank, die ASP.NET SQL Server-Registrierungstool.For ASP.NET to access a SQL database, you must use the ASP.NET SQL Server Registration Tool. Außerdem müssen Sie für das entsprechende Benutzerkonto den Zugriff auf die Datenbank und die Tabelle zulassen.In addition you must allow the appropriate user account access to the database and table. Weitere Informationen finden Sie unter Zugriff auf SQL Server aus einer Webanwendung.For more information, see Accessing SQL Server from a Web Application.

Bedingtes HTTP GET-basiertes ZwischenspeichernConditional HTTP GET Based Caching

In Web-HTTP-Szenarien eine bedingte HTTP GET wird häufig von Diensten intelligent HTTP-caching implementieren, wie beschrieben in der HTTP-Spezifikation.In Web HTTP scenarios a conditional HTTP GET is often used by services to implement intelligent HTTP caching as described in the HTTP Specification. Dazu muss der Dienst den Wert des ETag-Headers in der HTTP-Antwort festlegen.To do this the service must set the value of the ETag header in the HTTP response. Außerdem muss er den If-None-Match-Header in der HTTP-Anforderung überprüfen, um zu ermitteln, ob ein angegebener ETag mit dem aktuellen ETag übereinstimmt.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.

Für GET- und HEAD-Anforderungen verwendet CheckConditionalRetrieve einen ETag-Wert und überprüft diesen anhand des If-None-Match-Headers der Anforderung.For GET and HEAD requests, CheckConditionalRetrieve takes an ETag value and checks it against the If-None-Match header of the request. Wenn der Header vorhanden ist und eine Übereinstimmung vorliegt, wird eine WebFaultException mit dem HTTP-Statuscode 304 (Nicht geändert) ausgelöst, und der Antwort mit dem übereinstimmenden ETag wird ein ETag-Header hinzugefügt.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.

Eine Überladung der CheckConditionalRetrieve-Methode verwendet ein Datum der letzten Änderung und vergleicht es mit dem If-Modified-Since-Header der Anforderung.One overload of the CheckConditionalRetrieve method takes a last modified date and checks it against the If-Modified-Since header of the request. Wenn der Header vorhanden ist und die Ressource seitdem nicht geändert wurde, wird eine WebFaultException mit einem HTTP-Statuscode 304 (Nicht geändert) ausgelöst.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.

Für PUT-, POST- und DELETE-Anforderungen verwendet CheckConditionalUpdate den aktuellen ETag-Wert einer Ressource.For PUT, POST, and DELETE requests, CheckConditionalUpdate takes the current ETag value of a resource. Wenn der aktuelle ETag-Wert null ist, die Methode überprüft, ob der If-None-Match-Header den Wert hat "*".If the current ETag value is null, the method checks that the If-None- Match header has a value of "*". Falls der aktuelle ETag-Wert kein Standardwert ist, vergleicht die Methode den aktuellen ETag-Wert mit dem If-Match-Header der Anforderung.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 beiden Fällen löst die Methode eine WebFaultException mit dem HTTP-Statuscode 412 (Vorbedingungsfehler) aus, wenn der erwartete Header in der Anforderung nicht vorhanden ist oder der Wert die Bedingungsprüfung nicht besteht, und legt den ETag-Header der Antwort auf den aktuellen ETag-Wert fest.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.

Sowohl die CheckConditional-Methode als auch die SetETag-Methode stellt sicher, dass der für den Antwortheader festgelegte ETag-Wert ein gültiges ETag gemäß HTTP-Spezifikation ist.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. Dies schließt das Setzen des ETag-Werts in doppelte Anführungszeichen ein, falls diese nicht bereits vorhanden sind, sowie das ordnungsgemäße Versehen von internen doppelten Anführungszeichen mit Escapezeichen.This includes surrounding the ETag value in double quotes if they are not already present and properly escaping any internal double quote characters. Der Vergleich von schwachen ETags wird nicht unterstützt.Weak ETag comparison is not supported.

Das folgende Beispiel veranschaulicht die Verwendung dieser Methoden.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;
    }
}

SicherheitsüberlegungenSecurity Considerations

Für Anforderungen, die eine Autorisierung erfordern, sollten die Antworten nicht zwischengespeichert werden, da die Autorisierung nicht ausgeführt wird, wenn die Antwort aus dem Cache bereitgestellt wird.Requests that require authorization should not have their responses cached, because the authorization is not performed when the response is served from the cache. Die Zwischenspeicherung dieser Antworten würde eine ernste Sicherheitslücke darstellen.Caching such responses would introduce a serious security vulnerability. Anforderungen, die eine Autorisierung erfordern, stellen gewöhnlich benutzerspezifische Daten bereit. Aus diesem Grund bietet serverseitiges Zwischenspeichern auch keine Vorteile.Usually, requests that require authorization provide user-specific data and therefore server-side caching is not even beneficial. In solchen Situationen ist clientseitiges Zwischenspeichern oder der Verzicht auf Zwischenspeichern besser geeignet.In such situations, client-side caching or simply not caching at all will be more appropriate.