ASP.NET MVC 4.0 Chrome Caching - asp.net-mvc

I have code in place to disable caching in my MVC application. I'm using the following response headers. They seem to work in all browsers except for Chrome (currently using version 31.0.1650.48). Users are able to submit a form with model values. When they hit the back button I need the page to reload with a blank model. The headers appear to partially work since the request is hitting the action and returning the blank model. However the view isn't updating. The values from the previous post are being retained. I've tried clearing the ModelState but that doesn't work. Any suggestions? Thanks in advance!!
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1))
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(False)
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches)
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache)
filterContext.HttpContext.Response.Cache.SetNoStore()

Turning off autocomplete for the form fixed this for me. I appreciate all the input!
<form autocomplete="off"></form>

There is a way to do this in javascript for everything in one go like so...
document.getElementById("YourFormID").reset();
Just add an id to your form and all your inputs will reset on page load. Regardless if its a first time visit or a back button click with the page being cached. The biggest difference from your solution and this is that "the autocomplete attribute is new in HTML5". Which means it is not supported in older browsers, and though it does what you want it also prevents the user from autofilling fields. Meaning that for example on text types inputs users will not see a suggestion of words they may have entered on previous or other pages. You can see an example here.

Related

Refresh a Sitecore rendering after logon

I feel like this should be obvious, but I'm stumped. We're running Sitecore 7.1 with MVC.
There is a Header rendering that includes conditional logic depending on the status of Sitecore.Context.IsLoggedIn. Works fine.
There is a second rendering that either allows the user to log in OR displays account information. When the [HttpGet] acton is called, the controller checks IsLoggedIn and returns one of two views. When the [HttpPost] action is called (i.e. when the user logs in), The controller calls AuthenticationManager.Login() and then returns the view with the account info. Works fine.
It's a simple solution that allows us to place one rendering on the page, and it works great, except for one thing: the header rendering still shows the not-logged-in content immediately after logging in.
Caching is turned off on the header rendering and in the presentation details. When any link is clicked or the page reloads, the header updates to show the correct info. The problem is only after the initial request/response, when the login form submits and returns an alternate view. Although we've had a complete HTTP request/response cycle, it's like Sitecore doesn't bother to check anything except the rendering that was directly affected.
I know I can solve this by returning a hard Redirect() after logging in but that seems inelegant and creates annoyances, like losing ViewBag info.
What I am really looking for is a way to tell Sitecore, "hey, refresh that other rendering!"
The fact that I can find nothing at all on-line about this 'problem' tells me I might be doing something conceptually wrong.
As I see it there are two ways of handling this problem:
FormHandler
You use #Html.FormHandler to specify a Controller and an Action to handle the authentication. The FormHandler action will execute very early (see: https://twitter.com/dmo_sc/status/480001473745399809) in the page execution, before anything is rendered, and all your Renderings will have the same view of whether users are logged in or not.
Martina did a good writeup on Sitecore MVC and forms:
https://mhwelander.net/2014/05/28/posting-forms-in-sitecore-mvc-part-1-view-renderings/
https://mhwelander.net/2014/05/30/posting-forms-in-sitecore-mvc-part-2-controller-renderings/
Post-Redirect-Get
I really want Sitecore MVC to have this feature build in, as it is useful for all form submission scenarios (bar AJAX). The idea is to handle the POST request and work out what you want to respond (and store this in tempdata). Instead of returning a ViewResult you issue a redirect to the same URL, this forces a GET to the page (at this point all the logged in state is same for all Renderings) where you fish the result out of tempdata. Also P-R-G protects against resubmitting POST requests.
cprakash documented his experience doing P-R-G:
https://cprakash.com/2015/01/12/sitecore-mvc-form-post-simplified/
Off Topic: Multiple forms on single page
This will not solve the OP problem, but worth having a look at in this context:
http://reinoudvandalen.nl/blog/ultimate-fix-for-multiple-forms-on-one-page-with-sitecore-mvc/
In MVC, your renderings are executed sequentially, top to bottom. So if your header rendering comes before the login status rendering, it's going to be done before the user is logged in.
The elegant way to do this would probably be to do your post and update both elements via JavaScript. If you want to keep the header logic separate from the login status logic, your login status script could allow other components to register their own callbacks. You could even build out a client-side message bus, if you will be doing this sort of thing frequently.
You could take a look at Jeremy's approach:
https://jermdavis.wordpress.com/2016/04/04/getting-mvc-components-to-communicate/
The key takeaway, I think, is where he switches the order of the placeholders by placing the results into variables and then render them wherever you want them.
#{
HtmlString main = Html.Sitecore().Placeholder("MAIN");
HtmlString head = Html.Sitecore().Placeholder("HEAD");
}
<head>
#head
</head>
<body>
#main
</body>

jquery tablesorter issue with page number

I am developing an ASP.NET MVC 4 application using jquery.tablesorter.js, jquery.tablesorter.pager.js and jquery.tablesorter.widget.js. Now I get an issue with this tablesorter, that is, the page number is saved in the local storage.
I understand it is saved for some reasons. The problem is, for example, I last open the 3rd page of the table and leave the session, then re-open a session, it goes to the 3rd page automatically. If, for some reasons, there is not enough items for any item to go to the 3rd page, it simply shows an empty table and pager, and confuses the user.
Any idea is highly appreciated.
Thanks,
A. Zhang
If you don't want the pager to save the page & size, then set the savePages option to false.
If you do want the page to get saved, but you only want to use session storage, then set the storage_useSessionStorage widget option to true.
Please note: the above options only work with my fork of tablesorter.

How does Rails persist text in input field?

I have a regular text input field, whose value is submitted via AJAX. After I migrate away from this page, and hit Back button, I can still see the value of the field there.
My questions are:
Does most of modern browsers support this user-entered values?
How can I remove the persisted value using Rails?
Thank you.
Your browser is remembering the form input values and displaying them when you go back. This likely doesn't have anything to do with Rails*.
You can't really do anything via Ruby/Rails code to change this behavior, but you can do it with JavaScript. Here's a random SO question that covers it: Reset form on Back button.
I'm not sure if there's a perfect way to handle this in every browser. Also note that many users would prefer that the browser keep the form values they've entered.
Note: I only qualify with "likely" because it is possible to write an app that explicitly remembers form values and restores them when the page is visited again, but by default, Rails isn't going to do that. It'd involve a fair bit of Rails and JavaScript code.
Does most of modern browsers support this user-entered values?
Yes, I believe they all support it to various degrees
How can I remove the persisted value using Rails?
This is a client side issue, not a Rails issue. You could use javascript to clear the input fields
A similar question and answer: Clear all fields in a form upon going back with browser back button
BFCache? https://developer.mozilla.org/en-US/docs/Working_with_BFCache

Rails Nested Forms: Error when using back button and saving after deleting a record

I've noticed a problem with nested forms and i'm not sure how to solve it. My forms are working fine normally, this isn't really a question about how to get them to work. This question is more of a 'what should I do in this scenario'.
When I use a nested form via fields_for it works great. When I add in the javascript to be able to add and remove fields everything works great. I can add, save, remove, save, no problems. However If you edit an object with a nested form then delete one of the nested objects (via sending the {'_delete' => true} parameter with the object), then you use the back button and save that form again without deleting the same fields you will get an error.
Your browser caches the field that should no longer be there, then Rails tries to find the old object via the 'id' element in the hash and it fails, rightfully so. Is there anyway I can prevent this? Do I need to just manually inspect the hash to make sure the element is still there? Is there some way I can force a browser refresh or something? Thanks for your time.
Yes and no. Your application has very little control over browser behavior. If the browser sends information to your application that no longer has relevance the best you can do server-side is validate against that and present the user with a clean error message (or silently drop the invalid record ids, but that could be very confusing to the user.)
The alternative is to try and get the browser to stop caching the page in question, you may have seen this before in bank or other sensitive applications where you hit your back button and you're presented with a warning "this page has expired". You could use meta tags or http headers to set the expiry date in the past or use pragma: no-cache.

mvc and the back button

I'm new to mvc so I don't know if there is a trick to this or not. When a user runs a search on a site I'm building and I take them to the results page, if I click the back button the search form is empty. Is there some way to keep the form fields populated as they were when going back (without resorting to session)? Thanks.
Strange.
Fields should be there by default. What browser are you using?
If you're using a regular browser, then maybe your doing something weird, like, resetting the fields via JavaScript or something. Perhaps elaborating more on your current implementation would help diagnosing your problem?
A last solution would be saving the fields as a cookie and loading them via JavaScript on the forms page inside onLoad.

Resources