ASP.Net MVC 3 RTM. I am trying to use the OutputCache attribute in an action, but doesn't appear to be working. Here is the Http Request and Response.
Request URL:http://localhost/MyApp/Employee.mvc/GetImage?userId=myUserId
Request Method:GET
Status Code:200 OK
Request Headers
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Cookie:ASP.NET_SessionId=sessionIdStuff
Host:localhost
Pragma:no-cache
Referer:http://localhost/MyApp/Employee/Review/1/Index
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US)
AppleWebKit/534.13 (KHTML, like Gecko)
Chrome/9.0.597.98 Safari/534.13
Query String Parameters
userId:myUser
Response Headers
Cache-Control:private, no-store, max-age=3484
Content-Length:1428
Content-Type:image/jpeg
Date:Wed, 16 Feb 2011 22:59:14 GMT
Expires:Wed, 16 Feb 2011 23:57:19 GMT
Last-Modified:Wed, 16 Feb 2011 22:57:19 GMT
Server:Microsoft-IIS/5.1
Vary:*
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:3.0
X-Powered-By:ASP.NET
Here is the controller:
[HttpGet, OutputCache(Location= OutputCacheLocation.Client, VaryByParam="userId", Duration=3600, NoStore=true)]
public FileContentResult GetImage(string userId)
{
byte[] result;
using (var client = new WebClient())
{
client.Credentials = CredentialCache.DefaultCredentials;
result = client.DownloadData(string.Format(IntranetUrl, userId));
}
return File(result, "image/jpeg");
}
and my View:
<img alt="Employee Picture" src='#Url.Action("GetImage", "Employee", new { userId = Model.UserId, area=""})' width="75px" height="100px" />
I tried comparing with other static images that are getting cached and the only differences where these lines:
Cache-Control:private, no-store,
max-age=3484
This is included in my action, but not in the static images. Also, the static images had an ETag, but my action response did not.
Can anyone help why this might not be cached in the browser?
Thanks for any help..
Try remove: NoStore=true (or set NoStore = false), and it'll work :)
Related
I am trying to disable the caching on on the the pages. The reason - the page in question should display up to date data on each request and the data is coming from external XML feed.
I am using standard HttpWebRequest HttpWebResponse. All is working fine but I am getting some (I believe) caching issues where by querying XML feed URL directly I am getting more up to date data compared to my Controller/View data which uses the same URL.
XML feed URL is appended with random numbers on each request and Caching was disabled in the controller ([OutputCache(NoStore = true, Duration = 0)]) as well as in the ActionResult, which produces the following:
Response
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.1
X-AspNet-Version: 4.0.30319
X-Frame-Options: SAMEORIGIN
X-Powered-By: ASP.NET
X-UA-Compatible: IE=edge
Date: Thu, 04 Aug 2016 13:22:33 GMT
Content-Length: 75285
Request
pretty print
GET /investor-relations/share-price HTTP/1.1
Host: cms.crestnicholson-dev.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: ecos.dt=1470316952533; ASP.NET_SessionId=5lbh4v20kac0boadibjfwedr; IsAgreeToCookiePolicy=true
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
And still outdated/cached data is rendered on the pageā¦
If someone has any ideas/suggestions, It would be greatly appreciated.
Controller code:
[OutputCache(NoStore = true, Duration = 0)]
public class InvestorRelationsController : Controller
{
public ActionResult SharePrice()
{
Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
Response.Cache.SetValidUntilExpires(false);
Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
return PartialView(GetSharePrice());
}
private SharePriceModel GetSharePrice()
{
try
{
var xml = GetSharePriceXml();
return ParseSharePrice(xml);
}
catch (Exception)
{
return new SharePriceModel() {IsServiceUnavailable = true};
}
}
private SharePriceModel ParseSharePrice(string xml)
{
Guard.ArgumentNotNull(xml, "xml");
var model = new SharePriceModel();
var doc = new XmlDocument();
doc.Load(new StringReader(xml));
var root = doc.DocumentElement;
model.DateLastUpdated = root.SelectSingleNode("Time").InnerText;
model.Price = root.SelectSingleNode("CurrentPrice").InnerText;
model.Change = root.SelectSingleNode("Change").InnerText;
model.ChangePersentage = root.SelectSingleNode("PercentageChange").InnerText;
return model;
}
private string GetSharePriceXml()
{
Uri address = new Uri(SiteConfiguration.SharePriceFeedUrl);
Random random = new Random();
string url = address + "?random=" + random.Next();
// Set a default policy level for the "http:" and "https" schemes.
HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
HttpWebRequest.DefaultCachePolicy = policy;
HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
// Create the web request
var request = WebRequest.Create(url) as HttpWebRequest;
// Set type to POST
request.CachePolicy = noCachePolicy;
request.KeepAlive = false;
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add("Cache-Control", "no-cache");
request.Headers.Add("Cache-Control", "private");
// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
using (var reader = new StreamReader(response.GetResponseStream()))
{
// Console application output
return reader.ReadToEnd().Trim();
}
}
}
}
I have a problem when use HTTP post method in the following code:
let body = JSON.stringify(applicationLink);
let requestHeaders = new Headers();
var headers = new Headers();
headers.set('Content-Type', ['application/json']);
headers.set('Access-Control-Allow-Origin', ['*']);
let reqoptions = new RequestOptions({
headers: headers
});
return this._http.post(this._applicationLinksUrl + this._linkServicePath,body,reqoptions).map(res => res.json())
When I execute the code I see an error:
XMLHttpRequest cannot load http..... Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http....' is therefore not allowed access.
Request Method:OPTIONS is mde instead of post
Request URL:http://localhost:7001/workprocess-service/resources/links
Request Method:OPTIONS
Status Code:200 OK
Remote Address:[::1]:7001
Response Headers
view source
Allow:OPTIONS,POST,GET,HEAD
Content-Type:application/vnd.sun.wadl+xml
Date:Thu, 26 May 2016 11:10:25 GMT
Last-Modified:Thu, 26 May 2016 09:02:27 CEST
Transfer-Encoding:chunked
Vary:Accept
X-Powered-By:Servlet/3.0 JSP/2.2
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:access-control-allow-origin, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:7001
Origin:http....
Referer:http....
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
and my data is not linked to the request.
If I remove reqoption
return this._http.post(this._applicationLinksUrl + this._linkServicePath,body).map(res => res.json())
the request is a POST but i receive an error 415 ( Unsupported Media Type)
Request URL:http://localhost:7001/workprocess-service/resources/links
Request Method:POST
Status Code:415 Unsupported Media Type
Remote Address:[::1]:7001
Response Headers
view source
Connection:close
Content-Length:22
Content-Type:text/html; charset=UTF-8
Date:Thu, 26 May 2016 11:14:44 GMT
X-Powered-By:Servlet/3.0 JSP/2.2
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:48
Content-Type:text/plain;charset=UTF-8
Host:localhost:7001
Origin:http:....
Referer:http:.....
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
Request Payload
view source
{labelFR: "dsds", labelNL: "dsds", url: "dsds"}
labelFR
:
"dsds"
labelNL
:
"dsds"
url
:
"dsds"
My data is linked to the request
You need to make your server set the header Access-Control-Allow-Origin because you are sending a CORS "Cross Origin Resource Sharing" request. Which simply means you are sending the request to a url that's not the same as the url you are sending from.
I see your backend is servlet/3.0, you can enable CORS "for all origins" by adding a web filter
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
#WebFilter(urlPatterns = {"*"})
public class CORSFilter implements Filter{
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "*");
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
I am trying to pass an C# object in Odatacontroler Content method:
var resp = Content(HttpStatusCode.OK, vResult );
Where vResult is a C# object with two fields (List Messaages; bool IsValidEntity) .
At client when I tried getting response bellow unexpected response coming:
Id = 0x00000003, Status = RanToCompletion, Method = "{null}", Result =
"StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content:
System.Net.Http.StringContent, Headers:\r\n{\r\n Pragma: no-cache\r\n
Cache-Control: no-cache\r\n Date: Wed, 06 Jan 2016 07:04:25 GMT\r\n
Server: Microsoft-IIS/7.5\r\n X-AspNet-Version: 4.0.30319\r\n
X-Powered-By: ASP.NET\r\n Content-Type: application/json;
odata.metadata=minimal\r\n Content-Length: 97\r\n}"
For details below can be referenced:
Odata Controller: How to convert Odata response to C# object at client
*
Note: There are several links on this topic but it didn't work for me,
So I have to post the new one here.
*
Basically I'm trying to show the UIProgressView to show the data being fetched from the web service. Now problem is that I'm getting the expectedContentLength for almost all the service that I call from my application and the response headers contains the Content-Length. But for one of the web service's response it doesn't return the expectedContentLength, instead always returns -1.
Following are the response headers that I get for two different web service response :
- Response header for which I get the content length.(Data from service is not huge)
{
Connection = "Keep-Alive";
"Content-Length" = 2689;
"Content-Type" = "application/json";
Date = "Tue, 23 Jun 2015 08:19:04 GMT";
"Keep-Alive" = "timeout=5, max=98";
Server = "Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15";
"X-Powered-By" = "PHP/5.5.15";
}
- Response header for which I don't get the content length. (Response contains the huge data, no files to be downloaded just JSON data)
{
Connection = "Keep-Alive";
"Content-Type" = "application/json";
Date = "Tue, 23 Jun 2015 08:12:34 GMT";
"Keep-Alive" = "timeout=5, max=97";
Server = "Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15";
"Transfer-Encoding" = Identity;
"X-Powered-By" = "PHP/5.5.15";
}
The Above service response contains huge data. When tested the response on Advanced rest client chrome's extension It gives following response header with "Transfer-Encoding" = chunked;.
Date: Tue, 23 Jun 2015 12:01:20 GMT
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15
X-Powered-By: PHP/5.5.15
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
I used following links, but none of them helped me:
Link1 , Link2 , Link3
Please help me.
Thanks!
Updated code:
After setting the Content-Lenth header on server side I got the valid response with Content-Length header on Advanced rest client chrome's extension.
Date: Wed, 24 Jun 2015 05:25:48 GMT
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15
X-Powered-By: PHP/5.5.15
Content-Length: 1272347
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json
But on client side (i.e in iOS Application) I still didn't get the Content-Lenth header so that I can get the expectedContentLength value.
I still get "Transfer-Encoding" = Identity; in the response header on my side.
I have also set the Accept-Encoding header in the request as follows :
[req setValue:#"identity;q=0" forHTTPHeaderField:#"Accept-Encoding"];
Is there anything more to be done on either side(server/client).
I don't know how one gets the content length added at the server side - I had problems with this before, and in one case I had a similar situation as yours - the content length was visible by dumping all headers, but iOS didn't hand it to me in the delegate method. The standard way to get it is via:
- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
{
...
NSUInteger responseLength = response.expectedContentLength == NSURLResponseUnknownLength ? 1024 : (NSUInteger)response.expectedContentLength;
I actually entered a bug on this: rdar://15605995 "HTTP Get response is 200 but response.expectedContentLength = -1 even when a Content-Length is found in the headers"
2014-01-08 18:49:36.966 DB_Lookup[36824:3f07] YIKES:LEN=22162 {
"Cache-Control" = "must-revalidate";
Connection = "keep-alive";
"Content-Encoding" = gzip;
"Content-Length" = 22162;
"Content-Type" = "text/html; charset=UTF-8";
Date = "Wed, 08 Jan 2014 23:49:09 GMT";
Expires = 0;
"Front-End-Https" = on;
Pragma = "no-cache";
Server = "nginx/1.2.4";
"Strict-Transport-Security" = "max-age=2592000";
Vary = "Accept-Encoding";
"X-Content-Type-Options" = nosniff;
"X-Frame-Options" = SAMEORIGIN;
"X-Powered-By" = <Company>;
"X-<Company>-Server" = "<private>";
"X-XSS-Protection" = "1; mode=block";
}
for this code:
if(response.expectedContentLength == NSURLResponseUnknownLength) {
id len = httpResponse.allHeaderFields[#"Content-Length"];
if(len) {
responseLength = [len integerValue];
}
NSLog(#"YIKES:LEN=%# %#", len, httpResponse.allHeaderFields);
}
This is going to be really hard for me to special case. I'm accessing an internal company data base, I have to use name/password first, then get a code to my phone (which I later enter) to get in. Is there other info I could grab to help you? How can it be that the content length is clearly there in the header, but you don't see it and return it to me?
Apple closed my bug, saying "Works as Expected". Really!?!?!?!?!?!?!
[I don't know if NSURLSession fixed it or not.]
EDIT: I should have added that in the past, other sites I connected to DID result in a properly set 'expectedContentLength'.
I'm unable to successfully download a file from the server using a Web API get call. The download seems to start but then Chrome throws:
"Resource interpreted as Document but transferred with MIME type application/zip"
Firefox doesn't say that but the download still fails.
What am I doing wrong in the following setup?:
[HttpGet, Route("api/extractor/downloadresults")]
public HttpResponseMessage DownloadResultFiles()
{
int contentLength = 0;
this.ResultFiles.ForEach(f => contentLength = contentLength + f.FileSize);
var streamContent = new PushStreamContent((outputStream, httpContext, transportContent) =>
{
...zip files...
});
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
streamContent.Headers.ContentLength = contentLength;
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "result.zip"
};
var response = Request.CreateResponse();
response.StatusCode = HttpStatusCode.OK;
response.Content = streamContent;
}
I trigger the download via:
window.location.href = "api/extractor/downloadresults";
With the resulting headers:
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:ASP.NET_SessionId=ibwezezeutmu2gpajfnpf41p
Host:localhost:47384
Referer:http://localhost:47384/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Response Headers
Cache-Control:no-cache
Content-Disposition:attachment; filename=result.zip
Content-Length:436102
Content-Type:application/zip
Date:Mon, 16 Dec 2013 22:36:31 GMT
Expires:-1
Persistent-Auth:true
Pragma:no-cache
Server:Microsoft-IIS/8.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcbmV3VG9vbGJveFxUb29sYm94XFRvb2xib3guV2ViXGFwaVx0ZXJtZXh0cmFjdG9yXGRvd25sb2FkcmVzdWx0ZmlsZXM=?=
Have you tried changing the request headers, for example the accept header?
Also, here you can find a similar question, some of the solutions suggested there may help you.