Extra refresh after a submit - grails

I know that whenever you submit a form, you will refresh a page. But is there a way of using javascript or whatsoever that allows the webpage to refresh one more time after a submit button is being input?
Thank you guys so much.

I am guessing that what you need to implement is the Post, Redirect, Get pattern, which is the recommended way in Grails applications. if you type grails generate-controller [somedomainclassname], you will see that that controller actually employs this pattern.
It works as follows:
Your form submits to a action inside a controller, let's call it save()
Your save() action then performs the necessary operations to actually save the object, when it is done, it sends the browser a 'redirect', much like this: redirect(action: "show", id: mySavedObject.id)
This will cause the browser to issue a GET for the url /mycontroller/show/{id}
That request is picked up by the show action of your controller. It then goes on to display the object that was just created.
This approach plays well with HTTP semantics and avoids annoying "do you want to repost your form data" questions for the end user.

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>

Open new window from GSP and forward to external URL

I need some help. I am converting a Struts application to Grails.
There is a particular action I am trying to convert.
There is a form in a jsp that asks a user to select a customer from a dropdown list and the user clicks one of two buttons.
When the user clicks on the "View Reports" button, an onclick event calls a javascript function that issues window.open on a STRUTS action class, passing the selected customer and selected action.
In the action class the http request has some attributes set (request.setAttribute (..)) and a forward is performed to an external application. The attributes that where set are used by the application for sign on. This is done as a POST.
My problem is I am not quite sure how to wire this flow using the Grails framework. I was able to get as far as the user selecting a customer, clicking an actionSubmit button, reading the selected customer from params, adding my attributes to 'request' and then..I am stuck.
How to open a new window? (Tried javascript way as was done with Struts).
Also I am able to issue a redirect to the external site in the controller, however a redirect is done as a GET and not a POST, as well as the redirect is done in the same window. Any help in laying this out would be awesome. Thanks
You can't redirect a user from server using POST.
I can see some possible solutions:
1 . If you don't need to pass through your server to validate or request some data, you can use this:
<form action="http://someotherserver.com" method="post">
2 . Create a controller that redirect to a page in your own site and in this page make a treatment that receives the paramters and then redirect the user to another domain using ajax.
In Grails, I've used createLink, with the 'base' attribute to do this.
<g:createLink base="${params.dynamicURL}">Link</g:createLink>
I think something like this would work, but you can research it here: http://grails.org/doc/latest/ref/Tags/createLink.html

jQuery Mobile and Rails RESTful actions

I'm having a problem with how jQuery mobile works with RESTful actions in Rails.
For this explaination, let's assume I have a resource called Planet and a PlanetsController and I'm attempting to create a new Planet by sending a post request from /planets/new to /planets. If this action succeeds, my URL is now /planets even though it's actually showing /planets/1. If the action failed, my URL is also now /planets/ instead of /planets/new.
In both of these cases, if I click the Back button to go back to the index action, it won't work because jQuery Mobile thinks I'm already on /planets. I have to reload the page in order to get back.
Is there a way to fix this so normal Rails RESTful actions can be used?
I had the same issue as well, I just added data-ajax = "false" to my form with the downside of having no transitions. Or you can follow another solution I found here: http://www.adobe.com/devnet/html5/articles/jquery-mobile-and-rails.html#articlecontentAdobe_numberedheader_1

Best practice/design for a multi-page form in .NET MVC3

I am working on a web application that involves the user filling out a multi-step form that spans several pages. The form has tabbed navigation across the top (these links do not submit the current page) and a next button at the bottom (which does submit). I am considering several strategies for handling form submission/validation:
one action method and view per form page. When you hit next, it submits the form to the action method for the next page. If there are validation errors, you are redirected back to the previous page:
URL's are descriptive and can be copy-pasted
Only redirects in the error case
Since the redirect does not have the form data, we lose context about the submission which makes it hard to display certain error messages
The same validation logic works for redirecting the user if they try to visit a step in the flow that they aren't ready for yet
one action method and view per form page. When you hit next, it submits the form to the current page action. If there are validation errors, the same view is returned. Otherwise, we redirect to the next page action:
URL's are descriptive and can be copy-pasted
Redirects are very common (not sure if this is bad)
When displaying validation errors, we are in the same request as the form submission so we have full access to the invalid input
Have to pass additional context if we want the ability to, for example, add a "Previous" button which also submits
one action method for ALL pages. URL's contain additional context about the step being submitted (e.g. MyController/MyAction/{step}). The controller message selects which view page to return depending on validation and the current step.
URL's are not descriptive (e. g. if I submit step 1 to go to step 2, then the URL the user sees will be the same regardless of whether page 1 (invalid) or page 2 is returned
No redirects
When displaying validation errors, we are in the same request as the form submission so we have full access to the invalid input
A different method I haven't listed here
I have tried to enumerate what I see as some of the pros and cons of each method, but I would be interested to know:
What are other pros and cons of these methods? Are mine correct? Could some of the cons I've listed be designed around?
Is there a standard approach to this problem which I should be using? If so, why is it the standard approach?
I would highly recommend option 2 with a minor modification. You may want to think about also creating one view model per action/view as well. If you have one model that spans all the pages, validation will occur across ALL properties, meaning that even though the user can only edit part of the model on each screen, they could get validation warnings for properties they can't see. We did this recently in a project and it worked beautifully. You have to do some data manipulation in the back-end to combine everything back together, but it was worth it in the end.
As you said, your URLs would be deep-linkable, which means users can Copy/Paste, and more importantly, they can add the page as a favorite in their browser, allowing them to come back to the same place very easily. In my opinion this makes option 3 obsolete.
You will also benefit from the fact that all of your logic for navigation is occurring in one place. You'll have to store the state of the "wizard" on the client (which page you're currently on) so that your controller knows what to do on submit. You'll want to analyze the state of the wizard and make a decision for where the user needs to go next. If you go with option 1, you won't know where you "came from" and server-validation errors will be difficult to display to the client. This is a beautiful example of the POST - REDIRECT - GET pattern. Each page would have 2 actions, a GET that takes simple ids, and a POST which takes more complex models. Post the server, figure out where to go next, redirect to a GET.
Lastly, consider your previous button simply linking directly to the previous step, instead of submitting the form. Otherwise, the user could potentially get stuck on an invalid step. This happened to us and again, worked very nicely.
Hopefully this was helpful. Good luck!

What methods are available to stop multiple postbacks of a form in ASP.NET MVC?

A common web problem is where a user clicks the submit button of a form multiple times so the server processes the form more than once. This can also happen when a user hits the back button having submitted a form and so it gets processed again.
What is the best way of stopping this from happening in ASP.NET MVC?
Possibilities as I see it are:
Disable the button after submit - this gets round the multiple clicks but not the navigation
Have the receiving action redirect immediately - browsers seem to leave these redirects out of the history
Place a unique token in the session and on the form - if they match process the form - if not clear the form for a fresh submit
Are there more?
Are there some specific implementations of any of these?
I can see the third option being implemented as an ActionFilter with a HtmlHelper extension in a similar manner to the anti-forgery stuff.
Looking forward to hearing from you MVC'ers out there.
Often people overlook the most conventional way to handle this which is to use nonce keys.
You can use PRG as others have mentioned but the downside with PRG is that it doesn't solve the double-click problem, it requires an extra trip to the server for the redirect, and since the last step is a GET request you don't have direct access to the data that was just posted (though it could be passed as a query param or maintained on the server side).
I like the Javascript solution because it works most of the time.
Nonce keys however, work all the time. The nonce key is a random unique GUID generated by the server (also saved in the database) and embedded in the form. When the user POSTs the form, the nonce key also gets posted. As soon as a POST comes in to the server, the server verifies the nonce key exists in its database. If it does, the server deletes the key from the database and processes the form. Consequently if the user POSTs twice, the second POST won't be processed because the nonce key was deleted after processing the first POST.
The nonce key has an added advantage in that it brings additional security by preventing replay attacks (a man in the middle sniffs your HTTP request and then replays it to the server which treats it as a legitimate).
You should always return a redirect as the HTTP response to a POST. This will prevent the POST from occuring again when the user navigates back and forth with the Forward/Back buttons in the browser.
If you are worried about users double-clicking your submit buttons, just have a small script disable them immediately on submit.
You might want to look at the Post-Redirect-Get (PRG) pattern:
This really isn't MVC specific, but the pattern we follow on our web pages is that actions are performed with AJAX calls, rather than full page POSTs. So navigating to a url never performs an action, just displays the form. The AJAX call won't be in the history
Along with the disabling of buttons, you can add a transparent div over the entire web page so that clicking does nothing. We do this at my work and add a little friendly label saying processing request..
The most elegant solution I found was to use ActionFilters:
Blog post is here

Resources