Caching ASHX Image Response - c#

I have created an ashx file to generate image thumbnails on the fly. I would like to cache these images client side after they are called the first time.
URL:
~/image.ashx?dir=user&w=25&h=25&force=yes&img=matt.jpg
Code Behind:
public void ProcessRequest (HttpContext context) {
TimeSpan refresh = new TimeSpan(0, 15, 0);
context.Response.Cache.SetExpires(DateTime.Now.Add(refresh));
context.Response.Cache.SetMaxAge(refresh);
context.Response.Cache.SetCacheability(HttpCacheability.Server);
context.Response.CacheControl = HttpCacheability.Public.ToString();
context.Response.Cache.SetValidUntilExpires(true);
string dir = context.Request.QueryString["dir"];
string img = context.Request.QueryString["img"];
bool force = context.Request.QueryString["force"] == "yes";
double w = 0;
double h = 0;
...
context.Response.ContentType = "image/jpeg";
thumb.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}
Using the Dev Tools in Chrome I can see the following Response Header:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 26 Sep 2011 19:17:31 GMT
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH=...; path=/; HttpOnly
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: image/jpeg
Content-Length: 902
Connection: Close
Can someone enlighten me as to why this isn't caching on multiple calls with the same exact URL? Any tips would be greatly appreciated.

Surely this line:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Server);
Should be:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public);

Related

IIS is returning JSON instead of File (in Export to Excel functionality)

I have a web application that's being hosted on IIS 8. It uses VueJS, and ASP.NET Web API. It has the ability to export a grid to Excel, which works in our TEST environment, but doesn't work in our Production environment. In TEST, when the user clicks on the Export to Excel button, it allows the user to download the XLSX document in the web browser. But in Production, it returns JSON.
Here's the code I'm using to stream out the file:
var appRoot = HttpContext.Current.Server.MapPath("~/");
var savePath = string.Format("{0}\\Temporary_Files\\{1}.xlsx", appRoot, Guid.NewGuid());
workbook.SaveAs(savePath);
HttpResponseMessage document = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(savePath, FileMode.Open);
document.Content = new StreamContent(stream);
document.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
document.Content.Headers.ContentDisposition.FileName = "Export.xlsx";
document.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
document.Content.Headers.ContentLength = stream.Length;
return document;
Here's the response in TEST:
RESPONSE HEADERS
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 7713
Content-Type: application/octet-stream
Expires: -1
Server: Microsoft-IIS/8.5
Content-Disposition: attachment; filename=Export.xlsx
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Date: Fri, 04 Dec 2020 17:50:54 GMT
Here's the response in Production:
RESPONSE HEADERS
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Date: Fri, 04 Dec 2020 17:45:02 GMT
Content-Length: 373
RESPONSE BODY
{"Version":{"_Major":1,"_Minor":1,"_Build":-1,"_Revision":-1},"Content":{"Headers":[{"Key":"Content-Disposition","Value":["attachment; filename=Export.xlsx"]},{"Key":"Content-Type","Value":["application/octet-stream"]},{"Key":"Content-Length","Value":["7497"]}]},"StatusCode":200,"ReasonPhrase":"OK","Headers":[],"RequestMessage":null,"IsSuccessStatusCode":true}
You can try my way:
return File(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
reportFilename + "." + extension)

How can I repair a malformed value of a header on an HTTP response?

I'm trying to get the value of the Content-Type content header on an HTTP response.
private async void StartButton_Click(object sender, EventArgs e)
{
var client = new HttpClient();
// When I send a GET request to this website and print the response
var response = await client.GetAsync("https://www.npr.org/sections/13.7/2017/12/01/567727098/a-tax-that-would-hurt-sciences-most-valuable-and-vulnerable");
Console.WriteLine(response);
// [BELOW] You can clearly see: Content-Type: text/html;;charset=UTF-8
// However, the value is malformed (note the double semicolon) and becomes null
Console.WriteLine(response.Content.Headers.ContentType == null);
// True
}
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: no-referrer-when-downgrade
Strict-Transport-Security: max-age=604800; includeSubDomains
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Connection: keep-alive
Connection: Transfer-Encoding
Cache-Control: max-age=0
Date: Tue, 19 Jun 2018 10:38:01 GMT
Server: Apache
X-Powered-By: PHP/5.6.33
Content-Type: text/html;;charset=UTF-8
Expires: Tue, 19 Jun 2018 10:38:01 GMT
Last-Modified: Fri, 01 Dec 2017 15:41:00 GMT
}
How can I repair the malformed value of the Content-Type so it becomes text/html; charset=UTF-8 instead of null?
I tried to explain my question as simply as possible. If you have any questions or think I left something out, please let me know! :)
Thanks to Crowcoder's comment, I was able to develop the answer. Although, I feel like it's sloppy and could be made elegant.
private async void StartButton_Click(object sender, EventArgs e)
{
var client = new HttpClient();
var response =
await client.GetAsync(
"https://www.npr.org/sections/13.7/2017/12/01/567727098/a-tax-that-would-hurt-sciences-most-valuable-and-vulnerable");
Console.WriteLine(string.Join("; ",
response.Content.Headers.GetValues("Content-Type").First()
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)));
}
// text/html; charset=UTF-8

How to download file in C# with Content-Length: 0

I tried WebClient, HttpWebRequest, WebRequest and couple other ways to download file from specific server but every time the file is empty (0 byte). I discovered that in the response headers:
Pragma: Public
Content-Disposition: attachment; filename="hQPDAU0.mp3"
Content-Transfer-Encoding: binary
Connection: close
Accept-Ranges: bytes
Content-Length: 0
Cache-Control: max-age=1468800
Content-Type: audio/mpeg
Date: Tue, 08 Jul 2014 08:52:05 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Set-Cookie: sessioncode=4v0jgqiq.....1kulouk0c01; path=/; domain=.domain
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.4.29
the Conent-Length is 0. I've opened the URL in my browser and it forced it to download file. But how can I download file in C#?
Pass the URL to the WebMethod hope it works for you.
[WebMethod]
public static string ProcessIT(string downloadURL, string file_name)
{
// Create a new WebClient instance.
WebClient myWebClient = new WebClient();
string path = #"c:\";
string path_n_name = path + file_name;
// Download the Web resource and save it into the current filesystem folder.
myWebClient.DownloadFile(downloadURL, path_n_name);
return "SUCCESS";
}
public FileResult DownloadExcel(string filepath)
{
byte[] fileBytes = System.IO.File.ReadAllBytes(filepath);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet,
`enter code here`Path.GetFileName(filepath));
}
------------------------------------------------------------------------

I want that HttpResponse header do not include Set-Cookie

Client makes a GET request, here's api response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 26
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=636f48abd1e4ad4818a02dc087a9bd0c1be56fb972e821c7c8cf37553bc46cc3;Path=/;Domain=testtest11.azurewebsites.net
Date: Sun, 13 Apr 2014 19:57:08 GMT
Connection: close
I want the response header do not include
"Cache-Control", "Pragma", "Expires", "Server", "X-AspNet-Version",
"Set-Cookie"
In other words, I hope that the ideal Response.
HTTP/1.1 200 OK
Pragma: no-cache
Content-Length: 26
Content-Type: application/json; charset=utf-8
Date: Sun, 13 Apr 2014 19:57:08 GMT
Connection: close
how i can do?
example asp.net web api code:
public class ProductsController : ApiController
{
public HttpResponseMessage GetProduct(string id)
{
HttpResponseMessage respMessage = new HttpResponseMessage();
respMessage.Headers.Clear();
respMessage.Content = new ObjectContent<string[]>(new string[] { "value22", "value2" }, new JsonMediaTypeFormatter());
return respMessage;
}
}
Start with this article: http://www.strathweb.com/2012/05/output-caching-in-asp-net-web-api/
Web API doesn't support Output Cache in the box, filip made a pretty good library for it.

ASP.Net MVC sending file without content size. Browser doesnt prompt save dialog until transfer is finished

I am writing on the fly file zipper.
I cant calculate correct file size of a future archive, so can specify Content-Length.
This code did not prompt save file dialog until both Thread.Sleep() methods returned.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Download()
{
return new DelayedUnsepcifiedLengthZipArchiveResult();
}
}
public class DelayedUnsepcifiedLengthZipArchiveResult : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = "application/zip";
context.HttpContext.Response.CacheControl = "private";
context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.HttpContext.Response.AddHeader("content-disposition", string.Format("attachment; filename=\"{0}\"", "test.zip"));
context.HttpContext.Response.Flush();
Thread.Sleep(10000);
context.HttpContext.Response.Write("hello world");
context.HttpContext.Response.Flush();
Thread.Sleep(10000);
context.HttpContext.Response.Write("hello world2");
context.HttpContext.Response.Flush();
context.HttpContext.Response.End();
}
}
In Chrome and IE 10 I got save dialog after 20 secs...
Is it a way to fix it?
Update:
Fidler goes crazy. Not sure, maybe Fidler adds Conent-Length automatically. This is raw data I getting from fidler
At the start
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/zip
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 4.0
content-disposition: attachment; filename="test.zip"
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcV29ya1xBY2FkZW15XEhpZ2hMb2FkQ2hhblxEb3dubG9hZGVyXGhvbWVcZG93bmxvYWQ=?=
X-Powered-By: ASP.NET
Date: Mon, 04 Mar 2013 13:39:24 GMT
After download finished:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/zip
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 4.0
content-disposition: attachment; filename="test.zip"
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcV29ya1xBY2FkZW15XEhpZ2hMb2FkQ2hhblxEb3dubG9hZGVyXGhvbWVcZG93bmxvYWQ=?=
X-Powered-By: ASP.NET
Date: Mon, 04 Mar 2013 13:39:24 GMT
Content-Length: 23
hello worldhello world2
UPDATE 2:
fiddler coused such veird behaviour, problem closed. Turn off your debug proxies bros...

Categories