我有了返回报告文件,通常动作的MVC .NET应用程序.xslx
:
byte[] data = GetReport();
return File(data,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"filename.xlsx");
这在测试和在所有浏览器的伟大工程,但是,当我们把这个失败的IE6,7和8(所有适当的浏览器仍然正常工作)这无益错误的SSL网站:
这用在传统应用(非MVC),这一行动将替换工作。
我们不能告诉我们的用户,以局部改变任何东西 - 约60%仍使用IE6!
我怎样才能解决这个使用MVC?
更新
进一步深挖发现,这是一个IE6-8根本不合格。 据埃里克·法的IE内部博客出现这种情况,因为SSL连接时,IE对待no-cache指令作为一个绝对的规则。 因此,而不是不缓存副本,它认为无缓存意味着它不应该是可能的副本,即使保存到磁盘Content-Disposition:attachment
,并与下载位置的明确提示。
显然,这是错误的,但同时它的固定在IE9我们还是坚持了所有IE6-8用户。
使用MVC的行动过滤器属性生成以下标题:
Cache-Control:no-cache, no-store, must-revalidate
Pragma:no-cache
使用招改变这些的飞行,我们可以验证需要而不是返回的标题:
Cache-Control:no-store, no-cache, must-revalidate
注意顺序Cache-Control
必须有no-store
前 no-cache
,而且Pragma
指令必须完全删除。
这是一个问题 - 我们使用MVC的行动广泛属性和我真的不想从头开始重写它们。 即使我们可以,如果你尝试删除IIS抛出一个异常Pragma
指令。
如何使微软的MVC和IIS返回no-cache指令,微软的IE6-8可以在HTTPS处理? 我不希望允许响应(按照本的私人缓存类似的问题 ),或者忽略内置了一个覆盖方法的MVC(按我自己的答案,这仅仅是我目前最好的破解版)。
我想出了一个解决办法,但它是一个明确的黑客-这是一个新的高速缓存属性更换内置[OutputCache]
之一:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public sealed class IENoCacheAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.IsSecureConnection &&
string.Equals(filterContext.HttpContext.Request.Browser.Browser, "IE", StringComparison.OrdinalIgnoreCase) &&
filterContext.HttpContext.Request.Browser.MajorVersion < 9)
{
filterContext.HttpContext.Response.ClearHeaders();
filterContext.HttpContext.Response.AddHeader("cache-control", "no-store, no-cache, must-revalidate");
}
else
{
filterContext.HttpContext.Response.Cache.SetNoStore();
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
}
base.OnResultExecuting(filterContext);
}
}
这是一种解决方法充其量不过-我真正想要的是扩大现有[OutputCache]
和Response.Cache
结构,使它们具有适合于传统的IE所需的输出。
我有在类似的方法我有一个BaseController类
[OutputCache(Duration=0)]
public class BaseController : Controller
{
//snip snip: some utility stuff and shared endpoints among all my controllers
}
这引起了IE8上述问题。 运用[IENoCacheAttribute]
如上所示没有然而工作。 问题是,该指令filterContext.HttpContext.Response.ClearHeaders()
删除所有我的头,包括最终Content-Disposition
头等等导致文件下载到不正确的发生。
因此,我的方法是覆盖默认OutputCacheAttribute.cs
以这样的方式,在IE浏览器的情况下,它不适用任何类型的缓存头,特别是有问题的no-cache
的。
public class EnhancedOutputCacheAttribute : OutputCacheAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (!IsFileResultAndOldIE(filterContext))
base.OnActionExecuted(filterContext);
else
{
//try the best to avoid any kind of caching
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.Private);
filterContext.HttpContext.Response.Cache.SetMaxAge(new TimeSpan(0));
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.Now.AddMinutes(-5D));
}
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!IsFileResultAndOldIE(filterContext))
base.OnActionExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (!IsFileResultAndOldIE(filterContext))
base.OnResultExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if (!IsFileResultAndOldIE(filterContext))
base.OnResultExecuting(filterContext);
}
/// <summary>
///
/// </summary>
/// <param name="filterContext"></param>
/// <returns><c>true</c> for FileResults and if the browser is < IE9</returns>
private bool IsFileResultAndOldIE(dynamic filterContext)
{
return filterContext.Result is FileResult &&
filterContext.HttpContext.Request.IsSecureConnection &&
string.Equals(filterContext.HttpContext.Request.Browser.Browser, "IE", StringComparison.OrdinalIgnoreCase) &&
filterContext.HttpContext.Request.Browser.MajorVersion < 9;
}
}
下面是相应要点: https://gist.github.com/4633225