We had a silverlight application that maintained state when clicked on links and come back to it.
I was wondering if there's a way to implement something like that using Asp.net MVC? Basically right now user goes to a search page using a link in the banner, in the search page we display some items.. user clicks on one of them and another page opens up taking him to the main page that list that items information. From there the user can again click on search but this time of course a new search window opens up.
Am wondering if there is a way to load existing content form the already opened window into the new search window?
If it makes any difference the search page is ajax enabled.
As Shyju has pointed out, Http is stateless. There are several ways to store and share data between multiple pages in web applications.
Just to name a few, you can use:
Cookies (do not save security sensitive data such as passwords in
cookies)
Sessions
Browser's local storage (http://www.w3schools.com/html/html5_webstorage.asp)
In MVC, you can use ViewBag, ViewData or TempData
You can pass data as query parameters in URL
You do not want to maintain the state in ASP.Net MVC. It is a bad practice.
If you want to pass state between action methods, you can use TempData.
It uses Session State under the hood, and clear it automatically right after you retrieve the data.
ASP.Net offers some addition methods in addition to TempData. You can read more here. In your scenario, TempData is a best choice.
As we all know, HTTP is a stateless protocol, each HTTP request does not know about the previous request.
ASP.NET also provides state management techniques that can help us to maintain data when redirecting from one page to another. There are several ways.
Hidden Fields (is used to hide your data on client side. It is not directly visible to the user on UI but we can see the value in the page source).
Cookies (are used for storing the data but that data should be small. It is like a small text file where we can store our data, This are stored on client side memory in the browser).
Query String (generally used to pass value from one page to the next).
View Data (helps us to maintain the data when sending the data from controller to view. It is the dictionary of objects derived form ViewDictionary).
View Bag (same as View data, except the only difference is that view bag is the object of dynamic property).
Temp Data (is also a dictionary object as ViewData and stores value in key/value pair. It is derived from TempDataDictionary. It is mainly used to transfer the data from one controller to another controller).
Related
What is preferred way to share data (Object) between controllers with different routes and prevent data lost after reloading?
I need this object to prefill form values in my destination page which depends on choices in my source page.
Solutions I got so far are:
1- to send serialized Objects as query string parameter.
2- or using local storage and give special parameter to url so it knows when to fetch from local storage and when to open empty form.
Solutions which I can't use:
1- Shared service as my data would be lost after reload in this case.
Is there any other way, if not which way is more preferred?
note: there has to be no lost data after reloading page.
IMHO , there could be only 2 ways to handle this:
Using localStorage or sessionStorage
You use session management from server side keep the session consistent.
If it's just about retaining the data after page reload for a route, just go for sessionStorage. But it depends on the use case of your project.
i want my all check boxes checked whenever i come back from other pages, i want to maintain their states across pages using javascript.
I think you are asking how to store state for an individual session between requests. In this case, that state is checkbox values.
You have a choice to make first: do you want to store the data on the client (in the browser) or on your server?
Server Side
You can store this state on the server side with or without a "database" depending on how pedantic you want to be about the term.
If what you want is to avoid configuring an SQL RDBMS, you might find that the built-in storage options from most Java Servlet containers will work. In Tomcat, you can just use your Session objects as normal, but configure a "File Based Store" instead of a "JDBC Based Store." This will store session data to disk in files. Alternatively you can use StandardManager which uses in-memory storage, but does not persist session state across restarts.
Put simply, these will create a Java Map for each JSESSIONID issued by your server, and then keep the maps in memory, on disk, or in a JDBC database. For more information see: https://tomcat.apache.org/tomcat-7.0-doc/config/manager.html
Client Side
Here you have a few options as well. The driving factor is what level of browser you wish to support. If you can tolerate restricting your users to those who use a browser with HTML5 web storage and JavaScript enabled, things are pretty easy. If not, you can accomplish the same thing with a cookie.
The big downside to client-side storage is trust. Users (or software on their computer) can modify client-side storage. This goes for cookies, localStorage, and sessionStorage. Many developers forget this and introduce security vulnerabilities because of it. If this is for a real production web application, you'll want to wrap your state in an authenticator.
Here's a the first in a three article series on a way to convince your servlet container to put session state into cookies in a way that is transparent to your servlets. It is missing authentication, but you can add it by following guidance such as this bit from Rob Winch.
Now What?
Ok. You've decided to use client- or server-side storage for your checkbox values. Now what?
A simple (usually wrong) option is to store the checkbox input names and values in a map:
{"boxFoo": true,"BarBox":false}
The reason this is usually wrong is that it fails to distinguish which form your user was visiting. It means that if you apply this strategy to more than one form on your site, you'll have to worry about name collisions.
The next evolution is to have a structure keyed by form name and then field name. This would be a map like the following:
{ "formA": {"boxFoo": true,"BarBox":false},
"formQ": {"checkAlpha":true,"BetaCheck":false } }
This works, but will have annoying behavior when your users use multiple tabs. You can make that behavior more predictable for your users by using per-tab identifiers -- at the expense of space in your session object -- or by using AJAX to keep the fields in sync -- which has its own perils. Or you can do what most people do an just assume that the last submitted form overwrites the state from all previous ones, tabs be damned. That's much simpler to code, but more annoying to users.
I can propose some ways :
send http params (in hidden field) with check boxes flags which must stay checked in each new page requested by your application . You can factorize it with a function but it stays cumbersome to do.
store the check boxes marker flag in the http session. If the check boxes must stay checked in all the life of your user, it may be a suitable solution. Use may use a backing bean session for it as you use JSF.
Nevertheless, store the minimum of information in it.
store the information in a shared applicative cache to retrieve it. In this way, you stay stateless and you have not the drawback of the session if you use clustering in your servers.
There is maybe better as alternative.
You have to bind the value with a backing bean. As long as the backing bean is having the appropriate scope it will be retained on the page when you navigate to it.
I have graph with data in welcome page like widget(/welcome). when the user clicks the graph the page change to /home/default and the same graph should be displayed along with some extra data which is populated by Ajax call. What I want is to persist the graph data from /welcome into /home/default page. I don't want the data to go controller and back to the /home/default page. Kindly suggest.
In a nutshell, you need to set some state for the user and then when the /home/default page is rendered, you need to check that state and make corresponding changes to the presentation of the page.
This can be done either server-side (in the rendering of the page) or client-side (via Javascript adding things to the page).
If you do this client-side, then the state can be stored in a cookie, in LocalStorage or in a query parameter in the URL when you redirect. Then, you place Javascript code into /home/default that checks that state and adds content to the page dynamically based on the state.
If you do this server-side, then the state can be stored in a cookie or in some server-side data store and then when the /hoome/default page is rendered, your server side page rendering process can check the state for this particular user and modify the rendering of the page to include the desired content.
You have a plethora of options. The best solution depends on how your application is currently implemented -- whether in a framework or not, with sessions or not, etc. The principle whatever method you choose is almost identical: store a value and then retrieve it later.
Single Page Application (SPA)
If you aren't already using a framework, I would urge you to consider migrating to one as tasks like these are made infinitely more elegant in their implementation.
Service / Data Store
If you are building an SPA then you may not have to consider any of the options below... so long as it doesn't matter if the data is lost if the user performs a 'real' navigation that cannot be intercepted by the framework (for example, refreshing the page).
In Angular you can maintain a temporary data store in the form of a service. Simply store the data and then pick it up later from another controller. Similar functionality can be achieved in all other popular SPA frameworks:
Angular
Ember
React
Local Storage
Local Storage is available in IE8 and above and has a really simple API.
Angular: angular-local-storage
React: react-local-storage
Ember: ember-local-storage-adapter
jQuery: jStorage
IndexedDB
If you're into the cutting edge and aren't tied down by browser support, consider using IndexedDB. I don't recommend using this unless you are wanting to persist large amounts of data remotely on the client's machine. (It really does have bad support at the moment.)
Angular: angular-indexed-db
React: ???
Ember: ember-indexeddb-adapter
jQuery: jquery-indexeddb
Cookies
If your application is inflexible then cookies will be the easiest and least time-consuming. However Local Storage may be a contender.
Angular: $cookie service
React: react-cookie
Ember: ???
jQuery: jquery-cookie
I'm interested in implementing Backbone.js for some of the more repetitive in-page CRUD structures in our application (which is built on the CakePHP framework). I've been trying to get a hold on Backbone while figuring out how it would work in conjunction with Cake, and I"m a bit lost when it comes to separating the duties of the two sides.
Am I trying to jimmy something into my site that doesn't need to be there? Is there precedence for this kind of stack structure? I'm all ears at this point.
I'm actually working through the same situation right now (though with Python/Flask, but the same concepts should apply to any serverside language). Here is how the workflow for a page goes in my application. Just a note that I do NOT follow the single page application format; in my app, each major page is a full reload.
User requests a page, say a list of companies, /companies/listing/
Server does the routing, loading the correct controller
Controller loads first X companies from DB
Companies are encoded as JSON
Other meta data is loaded (such as total number of companies) and turned into JSON
The list page template is loaded and the JSON popped into a <script> tag within the template. Note here I do not fill in the listing table or anything along those lines, I let Backbone do all of that. I fill in the JSON here so the client doesn't have to make a second request for the initial set of companies
The list page is sent to the client. The server is done for now
The client has all the data it needs to start, so I take the JSON and pass it to my Backbone.View for the listing page
The view creates a collection for the models and manages a set of sub-views that represent the entries in the list
Any other processing/view creation happens such as the creation of pages, prev/next buttons, etc.
If the user clicks to the next page of companies, I fire an AJAX query to the server (/companies/listing/page/1 or something) which returns a new JSON string with a new set of models
Send the new set of models to my Backbone.View which refreshes everything
So really, the server is used for nothing but the actual loading of data, and the initial send of the template. I like this because it'll allow me to easily hook up new frontends (say, an iPad app or something).
For a form, in really broad strokes, I do something like this:
User requests form, /companies/edit/1
Server does permissions checking, loads entry, sends template/JSON to client. Server does not fill out the form with the data
Client uses JSON to fill out the form
Client modifies form, hits submit
All of their changes are applied to the model, the model is turned into JSON and sent to the server using AJAX
Server does validation and either sends error messages (in JSON) to client or updates the database and sends a success message
So, again, those are really broad strokes on how I've done it. In general, I use the server to grab data from the database, do server side validation (can't trust the client heh), and update the database.
If you have some specific questions, I'd be happy to try to share what I've learned so far.
I have a page that is generated from a bunch of grails templates being rendered, with javascript widgets and stuff, that specify parameters for a search engine we are developing. The problem is, if someone clicks on a person returned in the search results and it takes them to another page, and then they hit the browser back button, the search parameters and dynamically created widgets and previous search results are all gone.
I dont really want to have to programmatically re-build the page based on the search parameters (which I can save as a session variable), and I would then have to re-run the search query again to get the results back. is there a way to save a page just as it was created?
Thanks
Popup a javascript window with information about that person instead of taking them to another page. In the worst case set the target of the person link to _new and that will force open a new browser window/tab.
At some place the search parameters have to be saved. Either on server or client side. On the server side you only have the options session or flash scope.
On the client side you could store those values in a cookie. This needs some bits of javascript.
However theoretically the browser will keep manually changed form field-values out of the box. He is identifying the form fields by its name/id. It should not be necessary to do any programmatically things, except if you are loading some parts of the page via AJAX. Maybe you can doublecheck, that the input fields have static name/id pairs or you have some meta/cache/html settings, which prohibit such mechanism (double check, that your form does not have autocomplete="off" setting set. This will prevent the browser to refill your form fields.
Grails itself does not offer things like you need out-of-the-box (and I do not know if other frameworks have - maybe except for Seam, which has a concept of conversation scope; but even this feature will not work out-of-the-box if the user uses the browser back button). The easiest way is to make your search page some kind of cacheable (for the browser, by settings HTTP-headers or meta tags), so that the browser is not trying to reload the page from the server again, if the user presses the browser back button. And double check the autocomplete="off" setting.