Bit of Technology

  • Archive
  • About Me
    • Advertise
    • Disclaimer
  • Speaking
  • Contact

Building ASP.Net Web API RESTful Service – Part 11

February 8, 2014 By Taiseer Joudeh 32 Comments

Be Sociable, Share!

  • Tweet
  • Email
  • WhatsApp

This is the eleventh part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

  • Building the Database Model using Entity Framework Code First – Part 1.
  • Applying the Repository Pattern for the Data Access Layer – Part 2.
  • Getting started with ASP.Net Web API – Part 3.
  • Implement Model Factory, Dependency Injection and Configuring Formatters – Part 4.
  • Implement HTTP actions POST, PUT, and DELETE In Web API – Part 5.
  • Implement Resources Association – Part 6.
  • Implement Resources Pagination – Part 7.
  • Securing Web API – Part 8.
  • Preparing Web API for Versioning – Part 9.
  • Different techniques to Implement Versioning – Part 10.
  • Caching resources using CacheCow and ETag – Part 11. (This Post)

Update (2014-March-5) Two new posts which cover ASP.Net Web API 2 new features:

  • ASP.NET Web API 2 Attribute Routing.
  • IHttpActionResult as new response type and CORS Support.

Caching resources using CacheCow and ETag

In this post we’ll discuss how we can implement resource caching by using an open source framework for HTTP caching on the client and server, this framework is called CacheCow. It is created by Ali Kheyrollahi, we’ll cover in this post the server side caching.

API Source code is available on GitHub.

Using resource caching will enhance API performance, reduce the overhead on the server, and minimize the response size.

The form of caching we want to achieve here called Conditional Requests, the idea is pretty simple; the client will ask the server if it has an updated copy of the resource by sending some information about the cached resources it holds using a request header called ETag, then the server will decide weather there is an updated resource that should be returned to the client, or the client has the most recent copy, so if the client has the most recent copy the server will return HTTP status 304 (Not modified) without the resource content (empty body). By using Conditional Requests the client will send HTTP requests always to the server but the added value here that the server will only return full response 200 (OK) including resource content within the body only if the client has stale copy of the resource.

So what is ETag (Entity Tag)?

ETag is a unique key (string) generated at the server for particular resource, you can think of it as check-sum for a resource that semantically changes when the resource has updated.

ETag has two types, weak, and strong. The value of weak ETag is prefixed by W, i.e. ETag: “W/53fsfsd322″ and the strong ETag is not prefixed with anything, i.e. ETag: “534928jhfr4”. usually Weak ETags indicates that the cached resource is useful to be used for short time (In memory caching) and the strong ETag means that the resource caching is implemented using persistence storage and the content of the both resources (client and server) are identical byte for byte.

How ETags work?

By looking on the illustration below we will notice that at the beginning the client initiate HTTP GET request asking for the course with Id: 4 assuming that that this resource has not requested before, then the server will respond by returning the resource in the response body along with a generated ETag in the response header.

Now the client wants to request the same resource again (Course id: 4) by sending another HTTP GET, assuming that the client is interested in using caching, then the GET request initiated will include a header called If-None-Match with the value of the ETag for this resource, once the server receives this request it will read the ETag value and compare it with the ETag value saved on the server, if they are identical then the server will send HTTP status 304 (Not modified) without the resource content (empty body) and the client will know that it has the most recent copy of the resource.

For HTTP GET and DELETE we can use the header If-None-Match, but when updating a resource and we want to use ETags we have to send the header If-Match with the HTTP PUT/PATCH request, so the server will examine the ETag and if they are different; the server will respond with HTTP Status 412 (Precondition Failed) so the client knows that there is a fresher version of the resource on the server and the update won’t take place until the client has the same resource version on the server.

WebApiCachingETag

Configuring Web API to use CacheCow

After we had a brief explanation of how conditional requests and ETags work let’s implement this feature in our Web API.

Now we need to Install CacheCow server from NuGet, so open NuGet package manager console and type “Install-Package CacheCow.Server -Version 0.4.12” this will install two dlls, the  server version and common dll.

Configuring CacheCow is pretty easy, all we need to do is to create Cache Handler and inject it into the Web API pipeline, this this handler will be responsible to inspect each request and response coming to our API by looking for ETags and Match headers and do the heavy lifting for us.

To implement this open the file “WebApiConfig.cs” and at the end of the file add the below line of codes:

1
2
3
//Configure HTTP Caching using Entity Tags (ETags)
var cacheCowCacheHandler = new CacheCow.Server.CachingHandler();
config.MessageHandlers.Add(cacheCowCacheHandler);

Till this moment we have configured our API to use In-memory caching; this is the default configuration for CacheCow, this will be fine if you have a single server or for demo purposes, but in case of load balancers and web farms, the cache state should be persisted for the whole farm in single place and all web servers should be aware of this cache. In this case we need to configure CaschCow to use persistence medium (SQL Server, MongoDB, MemCache). But before moving to persistence store let we test the in-memory caching.

Cache Cow in-memory caching:

To test this we need to open fiddler and choose the Composer tab, we’ll issue a GET request to the URI: http://localhost:{your_port}/api/courses/4 The request will look as the image below:

CacheCowGet-WeakeTag

In this GET request we need to note the following:

  • The HTTP status response is 200 OK which means that server returned the resource content in the response body.
  • New two headers are added to the response which they are eTag and Last-Modified, we are interested here on the eTag value and we’ll get rid off the Last-Modified header later on as we’ll send conditional requests using eTag only.
  • The value of the eTag is weak (Prefixed with W) because we are using in-memory caching for now, in other words if we restarted IIS or shutdown its worker process all eTag values the client saving are useless.

Now after receiving the eTag header value, the client is responsible to send this value along with any subsequent requests for the same resource, the client will use the header “If-None-Match” when sending the request and the server will respond by HTTP status 304 with empty response body if the requested resource has not changed, other wise it will return 200 OK with new eTag value and resource content in the response body. To examine this let we open fiddler and issue GET request to the same resource (Course with Id: 4) as the image below:

CacheCow-WeakeTag-Response

In this GET request we need to note the following:

  • The HTTP status response is 304 Not modified which means that server returned empty body and the copy of the resource at client side is the latest.
  • The same eTag header value is returned in the response.

Now let’s move to configure CacheCow to use persistence caching medium (SQL Server) instead of in-memory caching.

Cache Cow persistence caching using SQL Server:

Configuring CacheCow to use SQL server is easy we need to install NuGet package which works with the medium we want to use, in our case SQL server, so open NuGet package manager console and type:  “Install-Package CacheCow.Server.EntityTagStore.SqlServer -Version 0.4.11“, this will install the requiered dlls.

Now open the file “WebApiConfig.cs” again paste the code snippet below:

1
2
3
4
5
6
//Configure HTTP Caching using Entity Tags (ETags)
var connString = System.Configuration.ConfigurationManager.ConnectionStrings["eLearningConnection"].ConnectionString;
var eTagStore = new CacheCow.Server.EntityTagStore.SqlServer.SqlServerEntityTagStore(connString);
var cacheCowCacheHandler = new CacheCow.Server.CachingHandler(eTagStore);
cacheCowCacheHandler.AddLastModifiedHeader = false;
config.MessageHandlers.Add(cacheCowCacheHandler);

What we implemented above is obvious, CacheCow needs to store caching information in SQL server, so we need to inform which database to use, in our case we’ll put this caching information in the same database of the API “eLearning”. Then we need to pass the SQL server eTagStore instance to the caching handler. As well we’ve turned off adding last modified header to the response because we are interested in eTag values only.

If you directly tried to issue any request against our API you will receive 500 error (Internal Server Error) because as we mentioned before CacheCow needs to store information about the cached resource on the server, this means it needs a table and some stored procedures to manipulate this table, so we need run SQL script before we go on. To do this navigate to the path where you NuGet packages are installed, usually they are on “{projectpath}packagesCacheCow.Server.EntityTagStore.SqlServer.0.4.11scripts“, open the file named “script.sql” and execute all its content against your local eLearning Database.

After running the script navigate to SQL server explorer and open eLearning database, you will notice that this script created a table named “CacheState” and another five stored procedures mainly used for manipulating this table.

To test this out we need to issue the same GET request as the image below:

CacheCow-StrongETag-Request

As you notice from the above image, the ETag value now is not weak, it is strong because we persisted it on SQL server, so if we opened the table “CacheState” you will notice that CacheCow has inserted new record including the ETag value, Route Pattern, Last Modified date, and binary hash key as the image below:

CacheCow-CacheStateTable

Now if the client sends any subsequent requests to the same resource, the same ETag value will be returned as long as no other clients updated the resource by issuing HTTP PUT/PATCH on the same resource.

So if the client includes this ETag value within the If-None-Match header then the server will respond by 304 HTTP status.

Now let’s simulate the update scenario, the client will issue HTTP PUT on the resource (Course with Id 4) including the ETag value in the header If-Match along with the request as the image below:

CacheCow-PUT-StrongETag

In this PUT request we need to note the following:

  • The HTTP status response is 200 OK which means that client has the most recent copy of the resource and the update of the resource has took place successfully.
  • New ETag has been returned in the response because the resource has been changed on the server, so the client is responsible to save this new ETag for any subsequent requests for the same resource.
  • The new ETag value and last modified date has been updated in table “CacheStore” for this resource.

Now if we directly tried to issue another PUT request using the old ETag (8fad5904b1a749e1b99bc3f5602e042b) we will receive HTTP Status 412 (Precondition Failed) which means that updating the resource has failed because the client doesn’t have the latest version of the resource. Now client needs to issue GET request to get the latest version  of the resource and the new generated ETag (ad508f75c5144729a1563a4363a7a158), let’s test this as the image below:

CacheCow-If-Match-PreconditionFailed

That’s all for now!

I hope you liked this tutorial, I tried my best to explain all important features of Web API which allows you to get started and build your RESTful API. You can always get back to the complete running source code on github.

Please feel free to drop any comment or suggestion to enhance this tutorial. if you have quick question please send me on twitter.

Be Sociable, Share!

  • Tweet
  • Email
  • WhatsApp

Related Posts

  • Integrate Azure AD B2C with ASP.NET MVC Web App – Part 3
  • Secure ASP.NET Web API 2 using Azure AD B2C – Part 2
  • Azure Active Directory B2C Overview and Policies Management – Part 1
  • ASP.NET Identity 2.1 Accounts Confirmation, and Password Policy Configuration – Part 2
  • ASP.NET Identity 2.1 with ASP.NET Web API 2.2 (Accounts Management) – Part 1

Filed Under: ASP.NET, ASP.Net Web API, Entity Framework, Web API Tutorial Tagged With: ASP.NET, CacheCow, ETag, HTTP Caching, REST, RESTful, Tutorial, Web API, Web Service

Comments

  1. zevs7772006 says

    February 9, 2014 at 1:20 pm

    As I can see, cashing with e-tags is helpfull for not very deep urls. Assume,you do a get request: /api/courses and recieve list of courses and e-tag for this. Than you do a post to /api/courses/4 for example. The list of courses changed, but getting another request for /api/courses will give you an old value. Is there a method to say to Cachecow to renew e-tags for some resourses?

    Reply
    • tjoudeh says

      February 10, 2014 at 1:58 am

      Thanks for your feedback, I agree with you, I wouldn’t turn on caching for a huge list that will change frequently, I’ll keep it for individual resources.
      I tried to turn off caching on specific routes i.e(/api/courses/) and keep it on single course (/api/courses/4) using AttributeBasedCacheControlPolicy with no luck. I asked CacheCow creator (@aliostad) on how to implement this. I’ll keep you posted.

      Reply
      • zevs7772006 says

        February 10, 2014 at 12:33 pm

        I’ll give you another example. Lets say /api/blogs gives us a list of blogs [e.g. Repository.GetAll(…)] and /api/blogs/10_01_14 will give a blog with comments and replies with one request to database [e.g. Repository.Include(b=>b.Comments).GetSingle(…)]. I don’t think blogs are written every day, but comments… So caching the list of blogs is better, but you may update your blog doing Post to /api/blogs/10_01_14, so e-tag for the list (/api/blogs) in some cases must be changed.

        Reply
      • pooranprasad says

        February 20, 2015 at 9:22 pm

        @tjoudeh Say there is a list of countries that I want to fetch .. GET api/countries GET api/states/?countryid=1

        Here data entry happens in normal MVC views. So, PUT/POST will not be called through APIs. Will it still update?

        Reply
        • Taiseer Joudeh says

          February 22, 2015 at 12:49 pm

          This has been for a while, but you need to do updates through API so SPs get executed, other than this it wont work.

          Reply
  2. zevs7772006 says

    February 9, 2014 at 3:26 pm

    Great article! It will be interesting to see how to work with etags in AngularJS. How to save them to cookies, best practices. And how to solve problem in my first comment. Thanx for this great work you do!

    Reply
    • tjoudeh says

      February 10, 2014 at 2:00 am

      Thank you, I wish I’ve more time to blog about this. But will keep it on my soon to-do list 🙂

      Reply
  3. stevanuz (@weaklinglifter) says

    February 9, 2014 at 8:16 pm

    Thanks for the article. Good to see how easy it is to do with CacheCow. Btw, W/ has nothing to do with storage? W/ means semantically equivalent and strong means byte-per-byte identical. I just recently implemented HTTP caching as well using ActionFilterAttribute. The idea is I can control which resources should be cached in controller. However, I still believe for example api/courses/4 should not be a good candidate for cache otherwise we could end up with for example api/courses/100001 with 100001 records in db/memory. api/courses is indeed yes to save bandwidth and data transfer. Here is my implementation of it, certainly may not be as good as CacheCow but maybe useful in some scenarios. http://weaklinglifter.blogspot.com/2014/02/webapi101-http-caching-on-action.html

    regards,
    stevanuz

    Reply
  4. Anderson says

    February 19, 2014 at 2:56 am

    Hi guy,
    I’ve read your articles “Building ASP.Net Web API RESTful Service Series” and “Tutorial for Building SPA using AngularJS”. Both of them are very useful. Thank for sharing it.

    It would be fantastic if you could demonstrate how authenticate in AngularJS app using WebApi like you showed in this article.

    regards,
    Anderson

    Reply
    • Taiseer Joudeh says

      February 19, 2014 at 5:34 am

      Thanks Anderson, I’ll consider blog about this soon.

      Reply
  5. Jeetender says

    February 27, 2014 at 2:07 pm

    I go through all the steps of making this web Api but when i run it and request for api/Courses
    than the constructor of baseApiController class is not invoking.

    Reply
    • Taiseer Joudeh says

      February 27, 2014 at 2:16 pm

      Strange, what you can do is to fork my working project on Github and compare it your working one, double check your routing configuration on class WebApiConfig.cs

      Reply
  6. Angel Valdes says

    March 10, 2014 at 12:08 am

    excellent example!!! very complete!, If you ever find a solution for api/courses Etag from been invalidated when any courses change, let us know. by the way… any suggestions in how to implement other authentications like oAuth?

    Reply
    • Taiseer Joudeh says

      March 11, 2014 at 2:05 pm

      Hello Angel, glad you like it. I bought recently this book and there is detailed chapter covers oAuth and different authentication techniques, will keep you posted once I read it.
      http://www.amazon.com/Pro-ASP-NET-Web-API-Services/dp/1430247258

      Reply
    • Taiseer Joudeh says

      August 28, 2014 at 1:43 pm

      Hi Angel,
      I know its too late now, but if you are still interested you ca check my new 4 parts detailed posts about Adding oAuth to Web API project.

      Reply
  7. Roopesh says

    May 29, 2014 at 9:26 pm

    Your article is “the best” compared to other examples. Very detailed and industry standard implementation. Keep it up,

    Thanks
    Roopesh

    Reply
    • Taiseer Joudeh says

      May 29, 2014 at 9:31 pm

      Thank you Roopesh, glad to hear this. It is my pleasure to write posts benefit the community 🙂

      Reply
  8. Huy Ngo (@huyngoduc_vn) says

    July 4, 2014 at 10:59 am

    Your series are very useful, It save my life. Thank you very much.

    Reply
    • Taiseer Joudeh says

      July 4, 2014 at 11:02 am

      Glad that you liked them, thanks for taking the time to comment 🙂

      Reply
  9. Devesh says

    September 9, 2014 at 10:38 am

    I have added CacheCow.Server Package and as you added the line in
    public static void Register(HttpConfiguration config)
    {
    // Web API configuration and services

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
    name: “DefaultApi”,
    routeTemplate: “api/{controller}/{id}”,
    defaults: new { id = RouteParameter.Optional }
    );
    var cacheCowCacheHandler = new CacheCow.Server.CachingHandler();
    config.MessageHandlers.Add(cacheCowCacheHandler);
    }

    but line var cacheCowCacheHandler = new CacheCow.Server.CachingHandler();
    is showing error:Error 2 ‘CacheCow.Server.CachingHandler’ does not contain a constructor that takes 0 arguments

    Reply
    • Taiseer Joudeh says

      September 9, 2014 at 10:42 am

      Hi Devesh,
      This has been for a while, I tell what is the exact issue now, but I recommend you to install the CacheCow.Server package using the same version I used in this project, most probably you’ve installed newer version which introduced breaking changes. To know the version installed open the file packages.config in my github and use this exact package.
      Hope this help.

      Reply
  10. Afzal says

    December 31, 2014 at 8:59 am

    Do let me know how does cache cow gets to know whether the resource is updated. I mean assuming our storage is SQL server like RDBMS, there is an update to the particular resource in rdbms. Unless server side code is executed, the application does not know about update on resource. Cache cow seems very similar outputCaching except that there is client negotiation is invoved. Is cache cow configured to verify whether the resource is getting updated?

    Reply
    • Afzal says

      December 31, 2014 at 10:26 am

      I just verified and got to know that cache cow verifies the http verbs like put/post/delete and based on that it gets info on updated resource . But what if there is an RPC style call that may not use exact http acton method on the resource but may update resource info in the RDBMS. In that case does cache cow gets to know whether the resource got updated

      Reply
  11. Chama says

    January 22, 2015 at 5:10 pm

    Nice resource!
    I was happy to get up and running in few minutes but my cache doesn’t seem to be invalidated after put. I have simple webapi with attribute routing that is api/tenants and I want the list to be updated after PUT is issued to update api/tenant/1 , for example. Did you find a way to invalidate the list?

    Here is what I have in my startup config:
    var etagStore = new SqlServerEntityTagStore(connString);
    var cacheHandler = new CachingHandler(config, etagStore);
    config.MessageHandlers.Add(cacheHandler);

    Reply
    • Taiseer Joudeh says

      January 24, 2015 at 1:14 am

      This had been for a while 🙂 So I really do not have clear answer now, but I recommend you to open issue with GitHub author, he should have better answer than me.

      Reply
  12. Dasun Sameera Weerasinghe says

    June 4, 2015 at 12:48 pm

    Just want you to thank for all your Web API tutorial series. 🙂 🙂 🙂 Keep this blog up!!!

    Reply
    • Taiseer Joudeh says

      June 5, 2015 at 1:47 am

      You are welcome, glad you liked them!

      Reply
  13. Prabhu says

    July 12, 2015 at 4:24 pm

    I thoroughly enjoyed this tutorials which gives makes the better understanding of the basics. Great going 🙂

    Reply
    • Taiseer Joudeh says

      July 15, 2015 at 1:11 am

      Thank you, always happy to help!

      Reply
  14. Mark s says

    February 14, 2018 at 3:14 pm

    Thanks for the nice article.

    Reply

Trackbacks

  1. Exploring Web API 2 Caching | Software Engineering says:
    May 18, 2014 at 9:28 pm

    […] https://bitoftech.net/2014/02/08/asp-net-web-api-resource-caching-etag-cachecow/ […]

    Reply
  2. Web API OData V4 Cache Part 9 | Software Engineering says:
    July 13, 2014 at 10:27 pm

    […] https://bitoftech.net/2014/02/08/asp-net-web-api-resource-caching-etag-cachecow/ […]

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About Taiseer

Husband, Father, Consultant @ MSFT, Life Time Learner... Read More…

Buy me a coffeeBuy me a coffee

Recent Posts

  • Integrate Azure AD B2C with ASP.NET MVC Web App – Part 3
  • Secure ASP.NET Web API 2 using Azure AD B2C – Part 2
  • Azure Active Directory B2C Overview and Policies Management – Part 1
  • ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – Part 5
  • ASP.NET Identity 2.1 Roles Based Authorization with ASP.NET Web API – Part 4

Blog Archives

Recent Posts

  • Integrate Azure AD B2C with ASP.NET MVC Web App – Part 3
  • Secure ASP.NET Web API 2 using Azure AD B2C – Part 2
  • Azure Active Directory B2C Overview and Policies Management – Part 1
  • ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – Part 5
  • ASP.NET Identity 2.1 Roles Based Authorization with ASP.NET Web API – Part 4

Tags

AJAX AngularJS API API Versioning ASP.NET Authentication Autherization Server Azure Active Directory B2C Azure AD B2C basic authentication C# CacheCow Client Side Templating Code First Dependency Injection Entity Framework ETag Foursquare API HTTP Caching HTTP Verbs IMDB API IoC Javascript jQuery JSON JSON Web Tokens JWT Model Factory Ninject OAuth OData Pagination Resources Association Resource Server REST RESTful Single Page Applications SPA Token Authentication Tutorial Web API Web API 2 Web API Security Web Service wordpress.com

Search

Copyright © 2019 · eleven40 Pro Theme on Genesis Framework · WordPress · Log in

loading Cancel
Post was not sent - check your email addresses!
Email check failed, please try again
Sorry, your blog cannot share posts by email.