Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No cache with HttpClient in Windows Phone 8

I've read that in order to disable caching while using get and post methods in HttpClient, I need to use a WebRequestHandler as my HttpClient's HttpClientHandler, and change its cache policy. However, WebRequestHandler is not within System.Net.Http.dll, but rather in System.Net.Http.WebRequest.dll, so I tried to add the .dll to the project as a reference. I got an error message:

Microsoft Visual Studio

A reference to a higher version or incompatible assembly cannot be added to the project.

Again, after a little search, I concluded that the .dll file was blocked because it was downloaded from another source. To unblock it, I went on trying the solution here. However, it didn't work either and I'm still getting the same error when I try to add the .dll file as a reference.

All I want to do is disable caching using my HttpClient, am I doing anything wrong here? I'm open to any type of advice or help.

My system is Windows 8.1 and I'm using Visual Studio 2013. The project I'm working on is a Windows Phone 8 application. The directory of .dll I'm trying to reference is "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Net.Http.WebRequest.dll". Thank you in advance.

like image 850
halileohalilei Avatar asked Jan 15 '14 10:01

halileohalilei


Video Answer


3 Answers

It's not possible to reference regular .NET assemblies in a Windows Phone 8 project. You can only use the .NET API for Windows Phone. This is a subset of regular .NET. See http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207211%28v=vs.105%29.aspx for more info.

The default caching of HttpClient (and HttpWebRequest) can be worked around by appending a value to the query string. For example, a guid.

string uri = "http://host/path?cache=" + Guid.NewGuid().ToString();

A better solution, like pointed out in the comment above, is to set the "If-Modified-Since" header. HttpWebRequest has it built in:

HttpWebRequest request = HttpWebRequest.CreateHttp(url);
if (request.Headers == null)
    request.Headers = new WebHeaderCollection();
// Make sure that you format time string according RFC.
// Otherwise setting header value will give ArgumentException for culture like 'ti-ER'
request.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString("r"); 

But you could add the header manually using an HttpClient I guess.

like image 186
denniebee Avatar answered Oct 07 '22 19:10

denniebee


If using Windows.Web.Http.HttpClient, the clean way to fix this issue from the client side is:

var httpFilter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
httpFilter.CacheControl.ReadBehavior = 
    Windows.Web.Http.Filters.HttpCacheReadBehavior.MostRecent;
var httpClient = new Windows.Web.Http.HttpClient(httpFilter);

This way, you avoid filling the app's cache with temp files when using random query strings. Each response is stored in the cache.

Of course, it is always recommended to fix the issue from the server side. Add the following header, and you won't need to worry about cache on each client:

Cache-Control: no-cache

Full response:

HTTP/1.1 200 OK
Content-Length: 31
Content-Type: text/plain; charset=UTF-8
Cache-Control: no-cache

...
like image 43
kiewic Avatar answered Oct 07 '22 19:10

kiewic


I found 3 ways

  1. Add a random Query String to the end of your URI (think Guid.NewGuid()) this will avoid caching on the client as the Query String will be different each time

string uri = "http://host.com/path?cache=" + Guid.NewGuid().ToString();

  1. Specify no cache in the OutgoingResponse header within your WCF service operation:
var __request = (HttpWebRequest)WebRequest.Create(url.ToString());
if (__request.Headers == null)
    __request.Headers = new WebHeaderCollection();
__request.Headers.Add("Cache-Control", "no-cache");
  1. markup your service operation with the AspNetCacheProfile attribute:
[AspNetCacheProfile("GetContent")]  
public ResultABC GetContent(string abc)  
{  
  __request = (HttpWebRequest)WebRequest.Create(abc);
  return __request;  
}

And update your web.config

<system.web>  
<caching>  
     <outputCache enableOutputCache="true" />  
     <outputCacheSettings>   
        <outputCacheProfiles >   
            <add name="GetContent" duration="0" noStore="true" location="Client" varyByParam="" enabled="true"/>   
        </outputCacheProfiles>   
    </outputCacheSettings>  
</caching>  
...  
</system.web>
like image 38
R00We Avatar answered Oct 07 '22 20:10

R00We