Caching-ondersteuning voor WCF-web-HTTP-services
Met .NET Framework 4.6.1 kunt u het declaratieve cachingmechanisme gebruiken dat al beschikbaar is in ASP.NET in uw WCF-web-HTTP-services. Met dit mechanisme kunt u reacties van uw WCF-web-HTTP-servicebewerkingen in de cache opslaan. Wanneer een gebruiker een HTTP GET
service verzendt die is geconfigureerd voor caching, stuurt ASP.NET het antwoord in de cache terug en wordt de servicemethode niet aangeroepen. Wanneer de cache verloopt, wordt de volgende keer dat een gebruiker een HTTP GET
servicemethode verzendt, aangeroepen en wordt het antwoord opnieuw in de cache opgeslagen. Zie ASP.NET Cacheoverzicht voor meer informatie over ASP.NET caching.
Basic Web HTTP-service opslaan in cache
Als u caching van web-HTTP-services wilt inschakelen, moet u eerst ASP.NET compatibiliteit inschakelen door de AspNetCompatibilityRequirementsAttribute service-instelling RequirementsMode toe te Allowed passen op of Required.
.NET Framework 4 introduceert een nieuw kenmerk met de naam AspNetCacheProfileAttribute waarmee u een cacheprofielnaam kunt opgeven. Dit kenmerk wordt toegepast op een servicebewerking. In het volgende voorbeeld wordt de AspNetCompatibilityRequirementsAttribute toepassing toegepast op een service om ASP.NET compatibiliteit mogelijk te maken en de GetCustomer
bewerking voor caching te configureren. Het AspNetCacheProfileAttribute kenmerk geeft een cacheprofiel op dat de cache-instellingen bevat die moeten worden gebruikt.
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class Service
{
[WebGet(UriTemplate = "{id}")]
[AspNetCacheProfile("CacheFor60Seconds")]
public Customer GetCustomer(string id)
{
// ...
}
}
Schakel ook ASP.NET compatibiliteitsmodus in het web.config-bestand in, zoals wordt weergegeven in het volgende voorbeeld.
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Waarschuwing
Als ASP.NET compatibiliteitsmodus niet is ingeschakeld en er AspNetCacheProfileAttribute een uitzondering wordt gebruikt.
De naam van het cacheprofiel die is opgegeven door de AspNetCacheProfileAttribute identificatie van een cacheprofiel dat wordt toegevoegd aan het configuratiebestand web.config. Het cacheprofiel wordt gedefinieerd met een <outputCacheSetting>
element, zoals wordt weergegeven in het volgende configuratievoorbeeld.
<!-- ... -->
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="CacheFor60Seconds" duration="60" varyByParam="none" sqlDependency="MyTestDatabase:MyTable"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
<!-- ... -->
</system.web>
Dit is hetzelfde configuratie-element dat beschikbaar is voor ASP.NET toepassingen. Zie voor meer informatie over ASP.NET cacheprofielen OutputCacheProfile. Voor web-HTTP-services zijn de belangrijkste kenmerken in het cacheprofiel: cacheDuration
en varyByParam
. Beide kenmerken zijn vereist. cacheDuration
stelt de hoeveelheid tijd in die een reactie in de cache moet worden opgeslagen in seconden. varyByParam
hiermee kunt u een queryreeksparameter opgeven die wordt gebruikt voor het opslaan van antwoorden in de cache. Alle aanvragen met verschillende parameterwaarden voor queryreeksen worden afzonderlijk in de cache opgeslagen. Zodra een eerste aanvraag is ingediend http://MyServer/MyHttpService/MyOperation?param=10
, worden bijvoorbeeld alle volgende aanvragen met dezelfde URI geretourneerd als reactie in de cache (zolang de cacheduur niet is verstreken). Antwoorden voor een vergelijkbare aanvraag die hetzelfde is, maar een andere waarde voor de parameterquerytekenreeksparameter hebben, worden afzonderlijk in de cache opgeslagen. Als u dit afzonderlijke cachinggedrag niet wilt, stelt u deze optie in varyByParam
op 'geen'.
SQL Cache-afhankelijkheid
Reacties van web-HTTP-services kunnen ook in de cache worden opgeslagen met een SQL-cacheafhankelijkheid. Als uw WCF-web-HTTP-service afhankelijk is van gegevens die zijn opgeslagen in een SQL-database, kunt u het antwoord van de service in de cache opslaan en het antwoord in de cache ongeldig maken wanneer de gegevens in de SQL-databasetabel worden gewijzigd. Dit gedrag wordt volledig geconfigureerd in het Web.config-bestand. Definieer eerst een verbindingsreeks in het <connectionStrings>
element.
<connectionStrings>
<add name="connectString"
connectionString="..."
providerName="System.Data.SqlClient" />
</connectionStrings>
Schakel vervolgens sql-cacheafhankelijkheid in binnen een <caching>
element in het <system.web>
element, zoals wordt weergegeven in het volgende configuratievoorbeeld.
<system.web>
<caching>
<sqlCacheDependency enabled="true" pollTime="1000">
<databases>
<add name="MyTestDatabase" connectionStringName="connectString" />
</databases>
</sqlCacheDependency>
<!-- ... -->
</caching>
<!-- ... -->
</system.web>
Hier is afhankelijkheid van DE SQL-cache ingeschakeld en wordt een poll-tijd van 1000 milliseconden ingesteld. Telkens wanneer de polling-tijd is verstreken, wordt de databasetabel gecontroleerd op updates. Als er wijzigingen worden gedetecteerd, wordt de inhoud van de cache verwijderd en wordt de volgende keer dat de servicebewerking wordt aangeroepen een nieuw antwoord in de cache opgeslagen. Voeg binnen het <sqlCacheDependency>
element de databases toe en verwijs naar de verbindingsreeks s in het <databases>
element, zoals wordt weergegeven in het volgende voorbeeld.
<system.web>
<caching>
<sqlCacheDependency enabled="true" pollTime="1000">
<databases>
<add name="MyTestDatabase" connectionStringName="connectString" />
</databases>
</sqlCacheDependency>
<!-- ... -->
</caching>
<!-- ... -->
</system.web>
Vervolgens moet u de instellingen voor de uitvoercache configureren binnen het <caching>
element, zoals wordt weergegeven in het volgende voorbeeld.
<system.web>
<caching>
<!-- ... -->
<outputCacheSettings>
<outputCacheProfiles>
<add name="CacheFor60Seconds" duration="60" varyByParam="none" sqlDependency="MyTestDatabase:MyTable" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
<!-- ... -->
</system.web>
Hier is de cacheduur ingesteld op 60 seconden, varyByParam
is ingesteld op geen en sqlDependency
wordt deze ingesteld op een door puntkomma's gescheiden lijst met databasenaam-/tabelparen, gescheiden door dubbele punten. Wanneer gegevens MyTable
worden gewijzigd, wordt het antwoord in de cache voor de servicebewerking verwijderd en wanneer de bewerking wordt aangeroepen, wordt er een nieuw antwoord gegenereerd (door de servicebewerking aan te roepen), in de cache opgeslagen en geretourneerd naar de client.
Belangrijk
Voor ASP.NET toegang tot een SQL-database moet u het ASP.NET SQL Server-registratieprogramma gebruiken. Daarnaast moet u de juiste gebruikersaccounttoegang tot de database en tabel toestaan. Zie Toegang tot SQL Server vanuit een webtoepassing voor meer informatie.
Voorwaardelijke CACHE op basis van HTTP GET
In web-HTTP-scenario's wordt een voorwaardelijke HTTP GET vaak gebruikt door services om intelligente HTTP-caching te implementeren, zoals beschreven in de HTTP-specificatie. Hiervoor moet de service de waarde van de ETag-header instellen in het HTTP-antwoord. Ook moet de If-None-Match-header in de HTTP-aanvraag worden gecontroleerd om te zien of een van de opgegeven ETags overeenkomt met de huidige ETag.
Voor GET- en HEAD-aanvragen CheckConditionalRetrieve neemt u een ETag-waarde en controleert u deze op basis van de If-None-Match-header van de aanvraag. Als de header aanwezig is en er een overeenkomst is, wordt er een WebFaultException met http-statuscode 304 (niet gewijzigd) gegenereerd en wordt er een ETag-header toegevoegd aan het antwoord met de overeenkomende ETag.
Een overbelasting van de CheckConditionalRetrieve methode neemt een datum van de laatste wijziging en controleert deze op de header If-Modified-Since van de aanvraag. Als de header aanwezig is en de resource sindsdien niet is gewijzigd, wordt er een met http-statuscode WebFaultException 304 (niet gewijzigd) gegenereerd.
Voor PUT-, POST- en DELETE-aanvragen wordt CheckConditionalUpdate de huidige ETag-waarde van een resource gebruikt. Als de huidige ETag-waarde null is, controleert de methode of de header If-None- Match een waarde van '*' heeft. Als de huidige ETag-waarde geen standaardwaarde is, controleert de methode de huidige ETag-waarde op de If-Match-header van de aanvraag. In beide gevallen genereert de methode een met een WebFaultException HTTP-statuscode 412 (Voorwaarde mislukt) als de verwachte header niet aanwezig is in de aanvraag of de waarde ervan niet voldoet aan de voorwaardelijke controle en de ETag-header van het antwoord op de huidige ETag-waarde instelt.
Zowel de CheckConditional
methoden als de SetETag methode zorgt ervoor dat de ETag-waarde die is ingesteld op de antwoordheader een geldige ETag is volgens de HTTP-specificatie. Dit omvat de omgeving van de ETag-waarde tussen dubbele aanhalingstekens als ze nog niet aanwezig zijn en alle interne dubbele aanhalingstekens correct ontsnappen. Zwakke ETag-vergelijking wordt niet ondersteund.
In het volgende voorbeeld ziet u hoe u deze methoden gebruikt.
[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;
}
}
Beveiligingsoverwegingen
Aanvragen waarvoor autorisatie is vereist, mogen hun antwoorden niet in de cache opslaan, omdat de autorisatie niet wordt uitgevoerd wanneer het antwoord vanuit de cache wordt verwerkt. Het opslaan van dergelijke reacties zou een ernstig beveiligingsprobleem veroorzaken. Aanvragen waarvoor autorisatie is vereist, bieden meestal gebruikersspecifieke gegevens en daarom is caching aan de serverzijde niet eens nuttig. In dergelijke situaties is caching aan de clientzijde of gewoonweg niet opslaan in cache geschikter.