How to prevent pdf cache all browsers? - asp.net-mvc-3

Even when the physical path is filled out on the navigation bar of all browsers it's showing a cached file.
The PROBLEM(with big letters because it's a big problem for us now) is that I already has cleared the client browser cache through a remote connection and I also already has applied a recycle on server application pool, but I'm still facing the same old problem :/ Someone facing something similar?
The following list include the actions applied until now that has not solved the problem:
01 - Response header:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.ClearHeaders();
filterContext.RequestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.RequestContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
filterContext.RequestContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
filterContext.RequestContext.HttpContext.Response.AppendHeader("Expires", "0");
filterContext.RequestContext.HttpContext.Response.AppendHeader("Last-Modified", "Wed, 08 Jan 2014 15:39:15 GMT");
filterContext.RequestContext.HttpContext.Response.AppendHeader("If-Modified-Since", "Tue, 07 Jan 2014 15:39:15 GMT");
base.OnActionExecuting(filterContext);
}
02 - Data annotation:
[OutputCache(NoStore = true, Duration = 0, Location = OutputCacheLocation.None, VaryByParam = "none")]
public ActionResult Avaliacao(int id)
{...
}
03 - Timestamp:
var _contents = memStream.GetBuffer();
memStream.Close();
return File(_contents, "application/pdf",
"RelatorioMensal-" + participante.Numero.GetValueOrDefault().ToString("00000") + "-" +
lote.Id.ToString("0000") + "-" + DateTime.Now.Ticks.ToString() + ".pdf");
04 - Application pool recycling
05 - Cache rule filter for .pdf files on IIS set to Prevent all caching
06 - Output cache setting: Enable cache and Enable kernel cache unchecked for testing purposes
07 - Clear cache through the code:
OutputCacheAttribute.ChildActionCache = new MemoryCache("NewDefault");
Ps.: I'm a MCSD - Web applications but don't tell it to anyone until I get this "simple" problem solved. Thanks ;)

Related

Caching issue with WebClient/HttpClient

I'm developing a code to poll a Bitstamp exchange ticker every 30 seconds. This is a code I have:
public IObservable<string> Stream(Uri way, WebClient wc)
{
Func<IObserver<string>, Task> Fun = async Observer =>
{
var res = await wc.DownloadStringTaskAsync(way);
Observer.OnNext(value: res);
};
return Observable.Create<string>(Fun);
}
public IObservable<string> GetDelay(int secs)
{
var exe = TimeSpan.FromSeconds(secs);
return Observable.Empty<string>("x").Delay(exe);
}
Stream(new Uri("https://bitstamp.net/api/ticker"), new WebClient { }).Concat(GetDelay(30))
.Repeat(5).Subscribe(res => Debug.WriteLine("got result: {0}", res));
The problem is that WebClient (and HttpClient, too) both return cached results after the first call, it can be seen by the same timestamp:
got result: {"high": "690.00", "last": "645.10", "timestamp": "1387715532" ... }
got result: {"high": "690.00", "last": "645.10", "timestamp": "1387715532" ... }
...
Even after turning the networks off they return the result normally so obviously they cache it somewhere. Adding something like "?cache=random" does not work because request parameters are not allowed for ticker on Bitstamp. Setting Headers[HttpRequestHeader.CacheControl] = "no-cache" for WebRequest does not work either.
How can I fix this weird caching behavior?
Solved by setting wc.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString(); before each subsequent call.
For Windows Phone Setting with Language=Chinese and "date+time" is not "24-hour clock" ,
the code wc.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString() causes exception throwing since DateTime.ToString() generates Chinese characters "下午" in the header.
The safer solution is to output the date time format as RFC1123 pattern:
req.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString("R");
This will ensure the date time is in format of "Sat, 05 Jul 2014 13:38:28 GMT", and there will no any Chinese characters within the HTTP headers.

JavaFX 2 - ObservableList<Message> to TableView

Hope I will get my question as clear as possible. I am working on a small java application using the JavaFX library for the gui. am doing a POP Connection and storing Messages as ObservableList. For this I am using javax.mail. I am passing this observablelist to a tableview and with the following i am passing the required values to the TableColumns:
fromColumn.setCellValueFactory(
new PropertyValueFactory<Message,String>("from")
);
subjectColumn.setCellValueFactory(
new PropertyValueFactory<Message,String>("subject")
);
dateColumn.setCellValueFactory(
new PropertyValueFactory<Message,String>("sentDate")
);
Subject and sentDate are beeing read-in perfectly. But unfortunately "from" is adding object-references to TableColumn, since the From-Attribute in the Message-Class is a InternetAdress-Object and its toString()-method isnt returning a string but probably a reference. And the result is the follwoing being shown in fromColumn:
[Ljavax.mail.internet.InternetAddress;#3596cd38
Anybody knows the solution how I could get the String-Value of the InternetAdress being showed in the mentioned Column?
Thanks in Advance
I think you need to define a custom cell value factory to get at the address information in the format you need rather than using the PropertyValueFactory.
The following sample is for a read only table - if the message data in the table needs to be editable, then the solution will be significantly more complicated.
fromColumn.setCellValueFactory(new Callback<CellDataFeatures<Message, String>, ObservableValue<String>>() {
#Override public ObservableValue<String> call(CellDataFeatures<Message, String> m) {
// m.getValue() returns the Message instance for a particular TableView row
return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
}
});
Here is an executable sample (plus sample data files) which demonstrate use of the custom cell value factory. Place the sample data files in the same directory as the application java program and ensure your build system copies the sample files to the build output directory which contains the compiled class file for the application. You will need the javamail jar files on your path to compile and run the application.
import java.io.*;
import java.util.Arrays;
import java.util.logging.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import javax.mail.*;
import javax.mail.internet.MimeMessage;
public class MailTableSample extends Application {
private TableView<Message> table = new TableView<Message>();
public static void main(String[] args) { launch(args);}
#Override public void start(Stage stage) {
stage.setTitle("Table View Sample");
final Label label = new Label("Mail");
label.setFont(new Font("Arial", 20));
table.setEditable(false);
TableColumn subjectColumn = new TableColumn("Subject");
subjectColumn.setMinWidth(100);
subjectColumn.setCellValueFactory(
new PropertyValueFactory<Message, String>("subject")
);
TableColumn sentDate = new TableColumn("Sent");
sentDate.setMinWidth(100);
sentDate.setCellValueFactory(
new PropertyValueFactory<Message, String>("sentDate")
);
TableColumn fromColumn = new TableColumn("From");
fromColumn.setMinWidth(200);
fromColumn.setCellValueFactory(new Callback<CellDataFeatures<Message, String>, ObservableValue<String>>() {
#Override public ObservableValue<String> call(CellDataFeatures<Message, String> m) {
try {
// m.getValue() returns the Message instance for a particular TableView row
return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
} catch (MessagingException ex) {
Logger.getLogger(MailTableSample.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
});
table.setItems(fetchMessages());
table.getColumns().addAll(fromColumn, subjectColumn, sentDate);
table.setPrefSize(600, 200);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10));
vbox.getChildren().addAll(label, table);
stage.setScene(new Scene(vbox));
stage.show();
}
private ObservableList<Message> fetchMessages() {
ObservableList<Message> messages = FXCollections.observableArrayList();
try {
Session session = Session.getDefaultInstance(System.getProperties());
for (int i = 0; i < 3; i++) {
InputStream mboxStream = new BufferedInputStream(
getClass().getResourceAsStream("msg_" + (i+1) + ".txt")
);
Message message = new MimeMessage(session, mboxStream);
messages.add(message);
}
} catch (MessagingException ex) {
Logger.getLogger(MailTableSample.class.getName()).log(Level.SEVERE, null, ex);
}
return messages;
}
}
msg_1.txt
From cras#irccrew.org Tue Jul 23 19:39:23 2002
Received: with ECARTIS (v1.0.0; list dovecot); Tue, 23 Jul 2002 19:39:23 +0300 (EEST)
Return-Path: <cras#irccrew.org>
Delivered-To: dovecot#procontrol.fi
Received: from shodan.irccrew.org (shodan.irccrew.org [80.83.4.2])
by danu.procontrol.fi (Postfix) with ESMTP id 434B423848
for <dovecot#procontrol.fi>; Tue, 23 Jul 2002 19:39:23 +0300 (EEST)
Received: by shodan.irccrew.org (Postfix, from userid 6976)
id 175FA4C0A0; Tue, 23 Jul 2002 19:39:23 +0300 (EEST)
Date: Tue, 23 Jul 2002 19:39:23 +0300
From: Timo Sirainen <tss#iki.fi>
To: dovecot#procontrol.fi
Subject: [dovecot] first test mail
Message-ID: <20020723193923.J22431#irccrew.org>
Mime-Version: 1.0
Content-Disposition: inline
User-Agent: Mutt/1.2.5i
Content-Type: text/plain; charset=us-ascii
X-archive-position: 1
X-ecartis-version: Ecartis v1.0.0
Sender: dovecot-bounce#procontrol.fi
Errors-to: dovecot-bounce#procontrol.fi
X-original-sender: tss#iki.fi
Precedence: bulk
X-list: dovecot
X-IMAPbase: 1096038620 0000010517
X-UID: 1
Status: O
lets see if it works
msg_2.txt
From cras#irccrew.org Mon Jul 29 02:17:12 2002
Received: with ECARTIS (v1.0.0; list dovecot); Mon, 29 Jul 2002 02:17:12 +0300 (EEST)
Return-Path: <cras#irccrew.org>
Delivered-To: dovecot#procontrol.fi
Received: from shodan.irccrew.org (shodan.irccrew.org [80.83.4.2])
by danu.procontrol.fi (Postfix) with ESMTP id 8D21723848
for <dovecot#procontrol.fi>; Mon, 29 Jul 2002 02:17:12 +0300 (EEST)
Received: by shodan.irccrew.org (Postfix, from userid 6976)
id 8BAD24C0A0; Mon, 29 Jul 2002 02:17:11 +0300 (EEST)
Date: Mon, 29 Jul 2002 02:17:11 +0300
From: John Smith <jsmithspam#yahoo.com>
To: dovecot#procontrol.fi
Subject: [dovecot] Dovecot 0.93 released
Message-ID: <20020729021711.W22431#irccrew.org>
Mime-Version: 1.0
Content-Disposition: inline
User-Agent: Mutt/1.2.5i
Content-Type: text/plain; charset=us-ascii
X-archive-position: 2
X-ecartis-version: Ecartis v1.0.0
Sender: dovecot-bounce#procontrol.fi
Errors-to: dovecot-bounce#procontrol.fi
X-original-sender: tss#iki.fi
Precedence: bulk
X-list: dovecot
X-UID: 2
Status: O
First alpha quality release, everything critical is now implemented. From
now on it's mostly stabilization and optimization. Features that can't break
existing code could still be added, especially SSL and authentication stuff.
msg_3.txt
From cras#irccrew.org Wed Jul 31 22:48:41 2002
Received: with ECARTIS (v1.0.0; list dovecot); Wed, 31 Jul 2002 22:48:41 +0300 (EEST)
Return-Path: <cras#irccrew.org>
Delivered-To: dovecot#procontrol.fi
Received: from shodan.irccrew.org (shodan.irccrew.org [80.83.4.2])
by danu.procontrol.fi (Postfix) with ESMTP id F141123829
for <dovecot#procontrol.fi>; Wed, 31 Jul 2002 22:48:40 +0300 (EEST)
Received: by shodan.irccrew.org (Postfix, from userid 6976)
id 42ED44C0A0; Wed, 31 Jul 2002 22:48:40 +0300 (EEST)
Date: Wed, 31 Jul 2002 22:48:39 +0300
From: Timo Sirainen <tss#iki.fi>
To: dovecot#procontrol.fi
Subject: [dovecot] v0.95 released
Message-ID: <20020731224839.H22431#irccrew.org>
Mime-Version: 1.0
Content-Disposition: inline
User-Agent: Mutt/1.2.5i
Content-Type: text/plain; charset=us-ascii
X-archive-position: 3
X-ecartis-version: Ecartis v1.0.0
Sender: dovecot-bounce#procontrol.fi
Errors-to: dovecot-bounce#procontrol.fi
X-original-sender: tss#iki.fi
Precedence: bulk
X-list: dovecot
X-UID: 3
Status: O
v0.95 2002-07-31 Timo Sirainen <tss#iki.fi>
+ Initial SSL support using GNU TLS, tested with v0.5.1.
TLS support is still missing.
+ Digest-MD5 authentication method
+ passwd-file authentication backend
+ Code cleanups
- Found several bugs from mempool and ioloop code, now we should
be stable? :)
- A few corrections for long header field handling
Sample program output:
This is a Java 8 version of jewelsea's solution but in awesome lambdas:
fromColumn.setCellValueFactory(m -> {
// m.getValue() returns the Message instance for a particular TableView row
return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
}
});
Lol, gotta love lambdas
Using the above mentioned solution, wether I use it as it is or I accept the advices of Eclipse i add a try/catch and a further return value, which looks like this at the end:
fromColumn.setCellValueFactory(new Callback<CellDataFeatures<Message, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Message, String> m) {
// m.getValue() returns the Message instance for a particular TableView row
try {
return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
});
The result is the same, I am getting a (visual) empty tableview. This means that even the tablecolumns are empty using this setCellFactury()-solution. Well, as workaround I could define a class where I could store al the three values as a String and then pass it to setCellValueFactory() using PropertyValueFactory, but I hope to get it done properly.
Any further advices?
best regards

html5 cache-manifest file in mvc3 and windows azure returns 500 error

i'm hosting an mvc3 web application in a windows azure web-role , and have recently added the html5 cash manifest.
in local environment everything works well , but once uploaded to dev environment on azure , i'm getting an HTTP 500 error when trying to access the manifest.
the cache manifest file is being served by an action and controller , similar to the technique sescribed in Dean Hume's article
the controller:
public ActionResult Manifest()
{
Response.ContentType = "text/cache-manifest";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.Cache.SetCacheability( System.Web.HttpCacheability.NoCache);
return View();
}
the View:
#{
Response.ContentType = "text/cache-manifest";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Layout = null;
}
CACHE MANIFEST
# 29/3/2012:V6
NETWORK:
*
CACHE:
#JS FILES
/Scripts/rolllo_1.0.js
/Scripts/rolllo_1.0.js
/Scripts/jquery.mobile-1.0b3.min.js
/Scripts/jquery.validate.min.js
/Scripts/jquery.validate.unobtrusive.min.js
/Scripts/jquery.unobtrusive-ajax.min.js
/Scripts/rolllo_1.0.js
#CSS FILES
/Content/Rtl.css
/Content/JQM/jquery.mobile-1.0b3.css
/Content/Site.css?v=2"
FALLBACK:
/Group/Offline
the _Layout:
<html manifest="#Url.Action("Manifest","Home")">
error messages:
from the chrome console : 'Application Cache Error event: Manifest fetch failed (500)'
and from fiddler :
HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/cache-manifest; charset=utf-8
Expires: -1
Date: Thu, 29 Mar 2012 09:32:22 GMT
Content-Length: 5875
i'd love some help.
The problem is probably that IIS is missing the MIME type in Azure. Take a look at:
http://blog.christian-heindel.de/2011/10/23/how-to-host-html5-offline-web-applications-on-an-iis-web-server/
But keep in mind for Azure you will have to do this in a startup task or in the WebRole OnStart method so it will happen anything your instance starts up.

Disconnecting Atmosphere sockets in Grails

I'm writing a Grails application which uses Atmosphere plugin. The connection works but every time I update the page in a browser I see that my web server adds a new Daemon thread which is never released afterwards.
After the thread count reaches 200 the web server freezes.
There seems to be no documentation explaining what is exactly the right way to handle the resources (disconnect) with the Atmosphere plugin?
My client code does this:
var connectedEndpoint = null;
$(function()
{
function callback(response)
{
if (response.transport != 'polling' && response.state != 'connected' && response.state != 'closed') {
if (response.status == 200) {
eval(response.responseBody);
}
}
}
$.atmosphere.subscribe('${resource(dir: '/atmosphere/channel')}', callback, $.atmosphere.request = {transport: 'streaming'});
connectedEndpoint = $.atmosphere.response;
});
$(window).unload( function ()
{
$.atmosphere.unsubscribe();
connectedEndpoint = null;
});
I use an atmosphere handler on the server side;
package demo
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import org.atmosphere.cpr.AtmosphereHandler
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
class DemoController implements AtmosphereHandler<HttpServletRequest, HttpServletResponse> {
#Override
public void destroy() {
println "destroy"
}
#Override
public void onRequest( AtmosphereResource<HttpServletRequest, HttpServletResponse> event) throws IOException
{
event.suspend()
}
#Override
public void onStateChange( AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) throws IOException
{
if (event.isSuspended())
{
event.resource.response.writer.with {
def message = event.message
write "set${message.paramName}(\"${message.id}\",\"${message.value}\");"
flush()
}
}
}
}
The destroy function of the handler is never called!
The next picture shows that I have 23 threads running. When I start my application there are about 6 of them and they are added every time I press F5! If I disable atmosphere new threads are not added so this problem is related to the Atmosphere. (I am using SpringSource Tools Suite on Windows7).
If the solution is not trivial I would appreciate detailed step-by step instructions or an example.
UPDATE: After deployment in Tomcat I have the following errors each 20 seconds:
Apr 02, 2012 2:35:15 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor host-manager.xml
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor manager.xml
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory docs
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory examples
Apr 02, 2012 2:35:17 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory ROOT
Apr 02, 2012 2:35:17 PM org.apache.coyote.http11.Http11AprProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Apr 02, 2012 2:35:17 PM org.apache.coyote.ajp.AjpAprProtocol start
INFO: Starting Coyote AJP/1.3 on ajp-8009
Apr 02, 2012 2:35:17 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 11401 ms
2012-04-02 14:41:17,122 [http-8080-39] ERROR cpr.AsynchronousProcessor - failed
to timeout resource AtmosphereResourceImpl{, hasCode-1035775543,
action=org.atmosphere.cpr.AtmosphereServlet$Action#f2718e,
broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
cometSupport=org.atmosphere.container.TomcatCometSupport#107fff7,
serializer=null,
isInScope=true,
useWriter=true,
listeners=[]}
2012-04-02 14:42:15,034 [http-8080-69] ERROR cpr.AsynchronousProcessor - failed
to timeout resource AtmosphereResourceImpl{, hasCode-58082012,
action=org.atmosphere.cpr.AtmosphereServlet$Action#ae4dd4,
broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
cometSupport=org.atmosphere.container.TomcatCometSupport#107fff7,
serializer=null,
isInScope=true,
useWriter=true,
listeners=[]}
2012-04-02 14:44:41,159 [http-8080-13] ERROR cpr.AsynchronousProcessor - failed
to timeout resource AtmosphereResourceImpl{, hasCode648226529,
action=org.atmosphere.cpr.AtmosphereServlet$Action#507e61,
broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
cometSupport=org.atmosphere.container.TomcatCometSupport#107fff7,
serializer=null,
isInScope=true,
useWriter=true,
listeners=[]}
....
Which web server are you using? Sound like the web server isn't detecting when the browser close the connection. You can add, in web.xml, the following timeout detector
org.atmosphere.cpr.CometSupport.maxInactiveActivity=30000 //30 seconds
I believe your issue is in your unload event. "$(window).unload". I know at least in chrome, you can't do much in the unload or beforeunload events. therefore, your browser is probably never firing the unsubscribe().
if u look at Atmospheres jquery pubsub sample, u can see the unsubscribing before connecting,
function connect() {
unsubscribe();
...
you can code a loop to check broadcasters by pushing insignificant data to validate the broadcasters periodically if they arent getting cleaned up. i need to research atmosphere more and hope for a better solution. hopefully you can clean up threads when the new connection is created from a refresh and let old ones expire with the session when the user leaves.

Can't specify StatusMessage in HttpStatusCodeResult

I have the following Controller method.
public ActionResult Save(IEnumerable<Model> models)
{
try
{
SaveModels(models);
}
catch (ApplicationException ex)
{
return new HttpStatusCodeResult(500, "error");
}
return new EmptyResult();
}
This will always return "Internal Server Error" as HTTP status description, no matter what message I give to the constructor.
Fiddler output:
HTTP/1.1 500 Internal Server Error
Server: ASP.NET Development Server/10.0.0.0
Date: Tue, 12 Apr 2011 12:44:09 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 3.0
Cache-Control: private
Content-Length: 0
Connection: Close
If I change the Status Code to 501 I get Not Implemented over the wire, same with 200 OK. And if I select a non-existant status code, like 535 it will just return the status code without any description. I can't see that I'm doing anything wrong according to the documentation and examples I've found from other people using this .
Can anyone see what I'm doing wrong?
I just had the same issue and based on #Mikael's comment, I tried deploying my application to an actual IIS server, and yes, you can specify the actual Status Description and it will be returned to the client side.
Why is it different with Cassini, I'm not really sure about.

Resources