【问题标题】:No cache with HttpClient in Windows Phone 8Windows Phone 8 中没有使用 HttpClient 的缓存
【发布时间】:2015-08-20 16:53:42
【问题描述】:

我读过,为了在HttpClient 中使用get 和post 方法时禁用缓存,我需要使用WebRequestHandler 作为我的HttpClientHttpClientHandler,并更改其缓存策略。但是,WebRequestHandler 不在 System.Net.Http.dll 中,而是在 System.Net.Http.WebRequest.dll 中,所以我尝试将 .dll 添加到项目中作为参考。我收到一条错误消息:

微软视觉工作室

不能引用更高版本或不兼容的程序集 添加到项目中。

再次,经过一番搜索,我得出的结论是 .dll 文件被阻止,因为它是从另一个来源下载的。为了解锁它,我继续尝试解决方案here。但是,它也不起作用,当我尝试添加 .dll 文件作为参考时,我仍然遇到同样的错误。

我想要做的就是使用我的 HttpClient 禁用缓存,我在这里做错了吗?我愿意接受任何类型的建议或帮助。

我的系统是 Windows 8.1,我使用的是 Visual Studio 2013。我正在处理的项目是一个 Windows Phone 8 应用程序。我试图引用的 .dll 目录是“C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Net.Http.WebRequest.dll”。提前谢谢你。

【问题讨论】:

  • 如何在您的请求标头中将 ifModifiedSince 标头设置为当前时间..

标签: c# .net windows-phone-8


【解决方案1】:

无法在 Windows Phone 8 项目中引用常规 .NET 程序集。您只能将 .NET API 用于 Windows Phone。这是常规 .NET 的一个子集。请参阅http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207211%28v=vs.105%29.aspx 了解更多信息。

可以通过将值附加到查询字符串来解决 HttpClient(和 HttpWebRequest)的默认缓存。例如,一个向导。

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

更好的解决方案,就像上面评论中指出的那样,是设置“If-Modified-Since”标题。 HttpWebRequest 已内置:

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"); 

但我猜你可以使用 HttpClient 手动添加标头。

【讨论】:

  • 谢谢,现在添加 IfModifiedSince 标头似乎可以正常工作。
  • 请注意,您应该使用DateTime.UtcNow.ToString("r");,以便按照 RFC 正确格式化时间戳。
  • 你救了我的命,我的头撞墙这么久了!最糟糕的是这种自动缓存只在 WP 应用程序上处理,而不是在通用应用程序上处理,wtf?!
  • 此解决方案可能是针对 Windows Phone 的黑客攻击。我尝试在 Xamarin 应用程序(也适用于 Windows Phone)中使用它,它导致服务器始终返回 304 Not Modified 响应,这是有道理的,因为如果有任何类型的缓存,If-Modified-Since“现在”很少为真服务器。最终为我工作的是 client.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue() { NoCache = true };
【解决方案2】:

如果使用Windows.Web.Http.HttpClient,从客户端解决此问题的干净方法是:

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);

这样,您可以避免在使用随机查询字符串时用临时文件填充应用程序的缓存。每个响应都存储在缓存中。

当然,始终建议从服务器端解决问题。添加如下头部,你就不用担心每个客户端的缓存了:

Cache-Control: no-cache

完整回复:

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

...

【讨论】:

    【解决方案3】:

    我找到了 3 种方法

    1. 在 URI 的末尾添加一个随机查询字符串(想想 Guid.NewGuid())这将避免在客户端缓存,因为查询字符串每次都会不同

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

    1. 在 WCF 服务操作的 OutgoingResponse 标头中指定不缓存:
    var __request = (HttpWebRequest)WebRequest.Create(url.ToString());
    if (__request.Headers == null)
        __request.Headers = new WebHeaderCollection();
    __request.Headers.Add("Cache-Control", "no-cache");
    
    1. 使用 AspNetCacheProfile 属性标记您的服务操作:
    [AspNetCacheProfile("GetContent")]  
    public ResultABC GetContent(string abc)  
    {  
      __request = (HttpWebRequest)WebRequest.Create(abc);
      return __request;  
    }
    

    并更新您的 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>
    

    【讨论】:

    • 选项 2 是避免从客户端缓存中检索结果的正确方法。
    【解决方案4】:

    我根据上面的解决方案写了一个HttpMessageHandler

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

    使用new HttpClient(new BypassCacheHttpRequestHandler(), true); 初始化您的HttpClient,然后您就可以随时绕过缓存。

    【讨论】:

    • 或者你可以只设置 HttpClient.DefaultRequestHeader。另外,更正确的做法是 httpClient.DefaultRequestHeader.CacheControl = new CacheControlHeaderValue() {NoCache=true};
    【解决方案5】:

    这让 windows phone 获取新数据而不是捕获数据

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

    设置了另一种选择

    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    

    如果您从 aspx 页面获取数据,则在服务器页面 Page_Load 中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多