Well formed URLs in Grails application - grails

I have an application, that register a user. I get the user through various pages, and everyone takes some data from the user, that info is stored in the session, and only in the last page, the data is stored in the DDBB.
When the first page is fulfilled by the user, he clicks the "next" button:
<div class='btn_sig_pag_uno'>
<!-- <fieldset id="barra">-->
<g:actionSubmit action="registro2"
title="${message(code:'infoPersonal.siguiente') }"
name="siguiente" class="siguiente"
value="${message(code: 'infoPersonal.siguiente', default: 'Siguiente')}"
style="cursor:pointer" />
<!-- </fieldset>-->
</div>
The in the controller, in the action "registro2" the data introduced by the user is validated, and "registro2.gsp" is presented... but the url presented is the same than in the first page. I would like it to be controller/action...and don't know why the url doesn't change.
Any help? Thank you!

What you need to do is to create an action to display registro2.gsp and then do a redirect after having execute registro2 like this:
redirect(action: "showRegistro2")
That way the URL will change.

I think this is the way forms work, and the way Grails deals with the actionSubmit. Form submits are by default POST. And since POSTs are about sending data (and not going somewhere, e.g. like a GET), the URL stays the same.
You can change your form to have method="GET", but I don't think this will get what you want when using Grails' actionSubmit since it still uses same URL (but with ?_action_actionSubmitActionName=param as URL param).
Usually you would just do a redirect to another action your action that receives the form POST:
redirect(action: "registroFinished")
And have a registroFinished.gsp for the end result.

Related

Return to previous page in ASP.Net Core MVC

From my client detail page I have a button to edit the client record which redirects to an edit page. I have a "return to client detail" link on the edit page which I want to redirect the user back to the previous client detail page.
<a asp-controller="Client" asp-action="Detail" asp-route-id="#Model.ClientID">Return to client detail</a>
Currently this works as expected but takes extra time as it reloads the detail page from scratch (ie running all the various db queries again). Since the user is really just cancelling the edit without any changes to the state of the client I am wanting to return the user to the previous detail page without having to go through the controller action again.
Essentially I am wanting to simulate the browser back button (to improve responsiveness) but i'm not sure how to implement this or whether it's good practice to do so. Some guidance would be appreciated.
Thanks
For IActionResult you can use this code:
public IActionResult Test()
{
return Redirect(Request.Headers["Referer"].ToString());
}
U know what? I hate JS so i will write answer with backend side. The HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. So simply read that and pass to view (always remember about XSS and validation, user can easly spoof HTTP request)
In action controller
if(Request.Headers["Referer"] != null)
{
ViewData["Reffer"] = Request.Headers["Referer"].ToString();
}
In view (razor)
#if(!string.IsNullOrWhiteSpace(ViewData["Reffer"]))
{
Return to client detail
}
You can use
<a href='javascript:history.go(-1)'>Return to client detail</a>
or onclick
Return to client detail
It should be like this
<input type="button" onclick= "history.go(-1)" value="Return to client detail" />
One note of caution using Request.Headers["Referer"] - if someone refreshes the destination page for some reason, Request.Headers["Referer"] will be empty.
Using history.go(-1) gives the expected behavior despite page refresh.
I think that you need to get rid of the idea of passing through the controller. If you need to browse quickliest with asp net core code about href you can try this.
<a asp-area="" onclick="history.go(-1);">Return to client detail</a>
I would never rely on my button, thinking a user will prefer it to browser back button.
I would say the correct way to solve this problem is to store the page state somewhere, for example, save ViewModel in TempData or Session. Then, if exists, load from it, instead of running db queries. It's quick and reliable.
This Request.Headers["Referer"] will not work if the user refresh the page or the page is been loaded twice, which mean, clicking back will not take you out of the current page.

Direct BeginUmbracoForm action to another page

I am trying to set up a global search box that posts to a search page in umbraco 7. This template uses a shared partial containing Html.BeginUmbracoForm() that points to a SurfaceController.
Since this is a global control, I want the form to be posted to the /search page instead of the current page. BeginUmbracoForm only seems to be able to post to the current page unless I'm mistaken.
I want something like RedirectToUmbracoPage(id), but clears this post values on redirect.
Is there a way to get an ActionResult like CurrentUmbracoPage which keeps the post values?
I would not try using surfacecontrollers for that purpose. Surfacecontrollers are auto routed. They are created to (e.g.) make #Html.Action(...) work on every umbraco page. Including postbacks on these actions or macros.
If you only need a "redirect" to the /search page, you don't need a surface controller. A simple partial will do the job.
<form action="/search" method="get">
Search <input type="search" name="q" />
</form>
Of course you can replace the url using some Umbraco logic like #Umbraco.TypedContentSingleAtXPath("//Search") or other Umbraco magic.
In the umbraco documentation project is an example where Html.Action is used.

In asp.net MVC5 how do we execute controller code after a View's submit button is clicked?

VS2013, MVC5, VB
I currently have a page that successfully sends a POST to a payment processor when the user clicks the payment button. I would like to do some additional actions in code after the request to process the payment is made in that View. I don't know how to do that. It may be that I'm thinking of this completely wrong, but that's where I am right now.
I'm assuming I would return to an ActionResult Function to do the final things in code and then go to another View to POST to the payment processor. I guess I'm asking how to force a View to POST immediately when a Return View() is executed so the user isn't required to click a Payment button again. Ergo my question about POSTing from a controller, because all I understand how to do is POST from a View.
Adding to the original post: Suppose I want to execute Sub ClearCart() (in reality it could be any number of things) after the Payment Submit button is clicked. So that means I don't want to POST away to the payment processor's website just yet, I want to first run one more piece of code on my end, then POST to the payment processor. But in order to do that, I only understand how to get back to a controller in order to run Sub ClearCart(). So now after I've run Sub ClearCart(), I have to setup another page with another Payment Submit button, and this time the POST to the payment processor can proceed because I've run the Sub ClearCart(). But that means a user is clicking Pay twice. Once to get me back where I can run some code, and then again when it's time to go to the payment processor for real.
I could very easily be lacking some fundamental concept and therefore my question doesn't make a lot of sense, but that's why I titled this thread the way I did. If I return to a Controller to run some code, I wondered how I can effectively force the POST from Controller code so it's transparent to the user. Am I explaining any better?
I thought in MVC all code is run in the Controllers, and the Views are simply to set up the page. I don't really run server side code from the page, right? And once I hit Submit on a POST to another website, I'm gone until the user and/or return payment information comes back. If I wanted to do anything after the user commits to the payment, I don't know or understand how to do that.
Additional add to the original post: There is a moment in time when the user clicks the submit button. Once that's done, action transfers to the destination in the 'action' parameter and I have no opportunity to do anything until the user or the destination site responds back. If I want to run some code after the Submit Button is clicked, how do I do that? When I started this thread I didn't really know what code to put in this thread to explain my question, but as a result of the comments, I now think this is what I need to show from the View that the user commits from:
<form id="simForm" method='post' action='https://test.authorize.net/gateway/transact.dll'>
...all the stuff presented or included in the view for the user to make his/her decision
<input type='submit' value="Submit Payment" class="btn btn-warning" />
</form>
I want to do things after the user commits, i.e. clicks the Submit Button, but it's too late once they click. I was thinking I could have a button that says Submit Payment, but instead of POSTing to my 'action' link above, POST back to a follow-on Controller where I can execute the code I want to run after the user makes their decision and before they leave my site. But I don't understand how to (1) initiate the real POST to the payment processor from within that follow-on Controller, or (2) force that follow-on Controller's View to execute a POST to the payment processor immediately without requiring another user action.
Now I've taken everyone on this horrible journey through my thinking, it just occurred to me what I'm wanting to do in a controller is redirect from the controller in a way that is a POST with all my page inputs to an external URL. Is there such a method? The only redirect I'm familiar with is for redirecting within the site.
Thanks.
Best Regards,
Alan
One way to do this is to use ajax to get back to a Controller Action, execute the code, and then let ajax finish with the Submit. The following code seems to work fine:
The Controller:
Public Class MiscController
Inherits Controller
Public Function ActionsBeforeSubmit() As ActionResult
ClearCart()
Return New EmptyResult()
End Function
End Class
The View:
<form id="simForm" method='post' target="_blank" action='https://test.authorize.net/gateway/transact.dll'>
...PAGE CONTENT HERE
<input type='button' onclick="UserCommit()" value="Submit Payment" class="btn btn-warning" />
</form>
<script >
function UserCommit() {
$.ajax({
url: '#Url.Action("ActionsBeforeSubmit", "Misc")'
async: false,
})
$("#simForm").submit()
}
</script>
When the button is clicked, the script UserCommit() is run. Within that script ajax runs the Controller Action ActionsBeforeSubmit. Updated this post: async: false required to force Submit to wait until ActionsBeforeSubmit is done. (although some texts suggest to not use async: false) After the Action finishes, the script performs the Submit.
Best Regards,
Alan

Symfony/Routing: Using POST to Avoid Query Params in URL

I want to pass the id from one action to the next action, but I do not want it seen in the URL. Is there a way to hide it?
Using Symfony, I have created a sign-up done page whose URL should be /signup/done
When the form is processed, I want to redirect to the signupSuccess action and pass the recently created ID for future use. So I use...
$this->redirect('#signup_done?id=' . $sign_up->getId());
The routing is as follows:
signup_done:
url: /signup/done
param: { module: SignUp, action: signupDone }
I have avoided the :id at the end because I don't want it in the URL.
But the resulting URL is /signup/done?id=1
Just as an experiment, I tried putting this on a template.
<?php echo link_to('Sign-up again', '#signup_done?id=1', 'post=true') ?>
Even when using post, the query parameter appears in the URL.
The need is: I want to pass the id from one action to the next action, but I do not want it seen in the URL. Is there a way to hide it?
I set the id as a parameter in the request using $request->setParameter('id', $id) and it was available in the next action.
This kept the URL clean.
If you want to post, you need a form. Back in symfony 1.2 there were helpers that you could call and made you just that - but they were removed for the promotion of promoting good code.
Depending on how you want the 'Sign up again' text to look, you can either create a simple form and a submit button, or create a link, attach a click listener, and create a form there via JS, finally post it.
Any parameter that you pass to the route in url_for, link_to and such end up in the get parameters.

ASP.NET MVC - How can I pass FormCollection data in a post to another Action?

I have a page "Results" with a form and when "submit" is clicked, the form is submmited to another Action. So far, so good...
But, this works fine just if user is logged in. If not, he will be redirected to "Login" page and my FormCollection loses its data.
Is there a way to persist this data without using TempData??
Thanks!!
I don't think that's possible. The only thing the system remembers during the redirect to the login page is the 'return url'. No post data is saved (this could be megabytes of data...)
You can use the Session object as alternative, or make sure that the user is logged in before you post.
Or, if it's just a search result, try to live without the POST, and use a GET (which also has other advantages)
I would prefer to disallow unauthorized user to visit "Results" page or at least to show him message "Please login first" instead of the form.

Resources