简体   繁体   中英

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.

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.

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

...

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> 

I wrote a HttpMessageHandler based on the solution above:

public class BypassCacheHttpRequestHandler : HttpClientHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.Headers.IfModifiedSince == null)
            request.Headers.IfModifiedSince = new DateTimeOffset(DateTime.Now);
        return base.SendAsync(request, cancellationToken);
    }
}

Use new HttpClient(new BypassCacheHttpRequestHandler(), true); to initialize your HttpClient then you can always bypass cache.

This for windows phone to get fresh data instead of catching data

Using(HttpClient httpClient = new HttpClient())
{
    httpClient.DefaultRequestHeaders.IfModifiedSince = DateTimeOffset.Now;
    //your code goes here`enter code here`
}

another alternative is set

Response.Cache.SetCacheability(HttpCacheability.NoCache);

in server page Page_Load if u get data from aspx page

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM