Udostępnij za pośrednictwem


Obsługa buforowania dla opartych na protokole HTTP usług sieci Web programu WCF

Program .NET Framework 4.6.1 umożliwia korzystanie z mechanizmu buforowania deklaratywnego dostępnego już w ASP.NET w usługach HTTP sieci Web WCF. Dzięki temu można buforować odpowiedzi z operacji internetowych protokołu HTTP programu WCF. Gdy użytkownik wysyła żądanie HTTP GET do usługi skonfigurowanej do buforowania, ASP.NET wysyła z powrotem buforowane odpowiedzi, a metoda usługi nie jest wywoływana. Gdy pamięć podręczna wygaśnie, następnym razem, gdy użytkownik wyśle żądanie HTTP GET, metoda usługi zostanie wywołana, a odpowiedź zostanie ponownie buforowana. Aby uzyskać więcej informacji na temat buforowania ASP.NET, zobacz ASP.NET Buforowanie Omówienie.

Podstawowa usługa HTTP sieci Web Buforowanie

Aby włączyć buforowanie usługi HTTP w sieci Web, należy najpierw włączyć ASP.NET zgodność, stosując AspNetCompatibilityRequirementsAttribute ustawienie usługi na Allowed wartość lub RequiredRequirementsMode .

Program .NET Framework 4 wprowadza nowy atrybut o nazwie AspNetCacheProfileAttribute , który umożliwia określenie nazwy profilu pamięci podręcznej. Ten atrybut jest stosowany do operacji usługi. Poniższy przykład dotyczy AspNetCompatibilityRequirementsAttribute usługi w celu włączenia zgodności ASP.NET i skonfigurowania GetCustomer operacji buforowania. Atrybut AspNetCacheProfileAttribute określa profil pamięci podręcznej, który zawiera ustawienia pamięci podręcznej do użycia.

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

Włącz również tryb zgodności ASP.NET w pliku Web.config, jak pokazano w poniższym przykładzie.

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

Ostrzeżenie

Jeśli ASP.NET tryb zgodności nie jest włączony i AspNetCacheProfileAttribute zostanie zgłoszony wyjątek.

Nazwa profilu pamięci podręcznej określona przez AspNetCacheProfileAttribute element identyfikuje profil pamięci podręcznej dodany do pliku konfiguracji Web.config. Profil pamięci podręcznej jest definiowany za pomocą elementu, <outputCacheSetting> jak pokazano w poniższym przykładzie konfiguracji.

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

Jest to ten sam element konfiguracji, który jest dostępny dla ASP.NET aplikacji. Aby uzyskać więcej informacji na temat profilów pamięci podręcznej ASP.NET, zobacz OutputCacheProfile. W przypadku internetowych usług HTTP najważniejsze atrybuty w profilu pamięci podręcznej to: cacheDuration i varyByParam. Oba te atrybuty są wymagane. cacheDuration Ustawia czas buforowania odpowiedzi w sekundach. varyByParam Umożliwia określenie parametru ciągu zapytania używanego do buforowania odpowiedzi. Wszystkie żądania wysyłane z różnymi wartościami parametrów ciągu zapytania są buforowane oddzielnie. Na przykład po wysłaniu początkowego żądania do http://MyServer/MyHttpService/MyOperation?param=10usługi wszystkie kolejne żądania wysyłane za pomocą tego samego identyfikatora URI będą zwracać buforowaną odpowiedź (o ile czas trwania pamięci podręcznej nie upłynął). Odpowiedzi dla podobnego żądania, które jest takie samo, ale mają inną wartość parametru ciągu zapytania, są buforowane oddzielnie. Jeśli nie chcesz tego oddzielnego zachowania buforowania, ustaw wartość varyByParam "none".

Zależność pamięci podręcznej SQL

Odpowiedzi usługi HTTP sieci Web można również buforować za pomocą zależności pamięci podręcznej SQL. Jeśli usługa HTTP sieci Web WCF zależy od danych przechowywanych w bazie danych SQL, może być konieczne buforowanie odpowiedzi usługi i unieważnienie buforowanej odpowiedzi, gdy dane w tabeli bazy danych SQL zmienią się. To zachowanie jest konfigurowane całkowicie w pliku Web.config. Najpierw zdefiniuj parametry połączenia w elemecie <connectionStrings> .

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

Następnie należy włączyć zależność pamięci podręcznej SQL w ramach <caching> elementu w elemecie <system.web> , jak pokazano w poniższym przykładzie konfiguracji.

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

W tym miejscu jest włączona zależność pamięci podręcznej SQL, a czas sondowania wynosi 1000 milisekund. Za każdym razem, gdy upłynie czas sondowania, tabela bazy danych jest sprawdzana pod kątem aktualizacji. Jeśli zostaną wykryte zmiany zawartości pamięci podręcznej zostaną usunięte, a przy następnym wywołaniu operacji usługi zostanie buforowana nowa odpowiedź. W elemencie dodaj bazy danych i odwołaj się do parametry połączenia w elemenciedatabases><, jak pokazano w poniższym przykładzie.<sqlCacheDependency>

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

Następnie należy skonfigurować ustawienia wyjściowej pamięci podręcznej w elemecie <caching> , jak pokazano w poniższym przykładzie.

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

Tutaj czas trwania pamięci podręcznej jest ustawiony na 60 sekund, varyByParam jest ustawiony na brak i sqlDependency jest ustawiony na rozdzielaną średnikami listę par nazw/tabel bazy danych oddzielonych dwukropkami. Gdy dane w pliku MyTable zostaną zmienione, buforowana odpowiedź dla operacji usługi zostanie usunięta i gdy operacja zostanie wywołana, zostanie wygenerowana nowa odpowiedź (wywołując operację usługi), buforowana i zwracana do klienta.

Ważne

Aby ASP.NET uzyskać dostęp do bazy danych SQL, należy użyć narzędzia ASP.NET rejestracji programu SQL Server. Ponadto należy zezwolić na dostęp odpowiedniego konta użytkownika do bazy danych i tabeli. Aby uzyskać więcej informacji, zobacz Uzyskiwanie dostępu do programu SQL Server z poziomu aplikacji internetowej.

Warunkowe Buforowanie oparte na protokole HTTP GET

W scenariuszach protokołu HTTP sieci Web warunkowe get http jest często używane przez usługi do implementowania inteligentnego buforowania HTTP zgodnie ze specyfikacją HTTP. W tym celu usługa musi ustawić wartość nagłówka ETag w odpowiedzi HTTP. Musi również sprawdzić nagłówek If-None-Match w żądaniu HTTP, aby sprawdzić, czy którykolwiek z określonych elementów ETag pasuje do bieżącego elementu ETag.

W przypadku żądań CheckConditionalRetrieve GET i HEAD przyjmuje wartość ETag i sprawdza ją względem nagłówka If-None-Match żądania. Jeśli nagłówek jest obecny i istnieje dopasowanie, WebFaultException zostanie zgłoszony kod stanu HTTP 304 (niezmodyfikowany), a nagłówek ETag zostanie dodany do odpowiedzi z pasującym elementem ETag.

Jedno przeciążenie CheckConditionalRetrieve metody przyjmuje datę ostatniej modyfikacji i sprawdza ją względem nagłówka If-Modified-Since żądania. Jeśli nagłówek jest obecny, a zasób nie został zmodyfikowany od tego czasu, WebFaultException zgłaszany jest kod stanu HTTP 304 (niezmodyfikowany).

W przypadku żądań CheckConditionalUpdate PUT, POST i DELETE przyjmuje bieżącą wartość elementu ETag zasobu. Jeśli bieżąca wartość ETag ma wartość null, metoda sprawdza, czy nagłówek If-None- Match ma wartość "*". Jeśli bieżąca wartość elementu ETag nie jest wartością domyślną, metoda sprawdza bieżącą wartość elementu ETag względem nagłówka If- Match żądania. W obu przypadkach metoda zgłasza WebFaultException kod stanu HTTP 412 (Warunek wstępny nie powiodło się), jeśli oczekiwany nagłówek nie znajduje się w żądaniu lub jego wartość nie spełnia warunków sprawdzania warunkowego i ustawia nagłówek ETag odpowiedzi na bieżącą wartość elementu ETag.

CheckConditional Zarówno metody, jak i SetETag metoda zapewniają, że wartość elementu ETag ustawiona w nagłówku odpowiedzi jest prawidłowym elementem ETag zgodnie ze specyfikacją HTTP. Obejmuje to otaczanie wartości ETag w cudzysłowach podwójnych, jeśli nie są one jeszcze obecne i prawidłowo ucieczki od wewnętrznych znaków podwójnego cudzysłowu. Porównanie słabego elementu ETag nie jest obsługiwane.

W poniższym przykładzie pokazano, jak używać tych metod.

[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;
    }
}

Zagadnienia związane z zabezpieczeniami

Żądania wymagające autoryzacji nie powinny mieć buforowanych odpowiedzi, ponieważ autoryzacja nie jest wykonywana, gdy odpowiedź jest obsługiwana z pamięci podręcznej. Buforowanie takie odpowiedzi wprowadziłyby poważne luki w zabezpieczeniach. Zwykle żądania wymagające autoryzacji zapewniają dane specyficzne dla użytkownika i dlatego buforowanie po stronie serwera nie jest nawet korzystne. W takich sytuacjach buforowanie po stronie klienta lub po prostu nie buforowanie w ogóle będzie bardziej odpowiednie.