Grails form submit causes 404 - grails

I have created a very simple form for signing up a user
<g:form name="signupForm" url="[controller:'users', action:'signup']">
<g:textField name="username" placeholder="Username" />
<g:passwordField name="password" placeholder="Password" />
<g:textField name="email" placeholder="Email" />
<g:actionSubmit class="right" value="Signup" action="update" />
</g:form>
When I click the submit button I get a 404 error The requested resource is not available. However, if I navigate to the exact same URL manually (or even just select the address bar on the 404 error page and press enter) then it works!
My controller looks like this, it's very simple.
class UsersController {
def signup() {
render "Hello World"
}
}
Sorry if this is a noob question, but I've looked all over the Grails docs and can't figure out why this is happening. Any help much appreciated. Thanks.

The g:actionSubmit has the parameter action="update" which will push it to the UsersController def update which isn't there so it will throw a 404.
You can remove the action="update" or add that action to the controller.
http://grails.org/doc/latest/ref/Tags/actionSubmit.html
There is also a g:submitButton you can use instead.
http://grails.org/doc/latest/ref/Tags/submitButton.html

Related

Action in grails form is not working

I am trying to make a simple creation of account and when create button is clicked it should perform the action "create" but I get an error saying that
HTTP Status 404 - "/WEB-INF/grails-app/views/users/create.gsp" not found.
Here is my code block for the index.gsp
<!-- CREATEFORM -->
<div id="id02" class="modal">
<g:form class="modal-content animate" controller="users" action="create">
<div class="imgcontainer">
<span onclick="document.getElementById('id02').style.display='none'" class="close" title="Close Modal">×</span>
<div class="container" style="text-align:center">
<b><h style="font-family: Arial, Helvetica, sans-serif; font-size: 30px">CREATE AN ACCOUNT</h></b><br/>
<input type="text" placeholder="Enter Username" name="uname" required/>
<input type="password" placeholder="Enter Password" name="psw" required/>
<input type="text" placeholder="First Name" name="firstName" required/>
<input type="text" placeholder="Last Name" name="lastName" required/>
<input type="text" placeholder="Age" name="age" required/>
<br/>
<input type="date" placeholder="Birth Date" name="birthdate" required/>
<br/>
<input type="text" placeholder="Student Number" name="studno" required/><br/>
<label>
<input type="checkbox" checked="checked" name="remember"> Remember me</input>
</label>
<br/>
<button type="submit" style="width: 100px; margin-right:10px;" >Create</input>
<button type="button" onclick="document.getElementById('id02').style.display='none'" class="cancelbtn">Cancel</button>
</div>
</div>
</g:form>
</div>
and Here is my code block for the usersController.
class usersController {
def index(){}
def create()
{
new Users(userid:params.uname,password:params.psw).save()
new UserInfo(studentno:params.studno,age:params.age,birth_date:params.birthdate,first_name:params.firstName,last_name:params.lastName,user_id:params.uname).save()
}
}
And here's the error
HTTP Status 404 - "/WEB-INF/grails-app/views/users/create.gsp" not found.
Because you are saving data using create action but after saving data there is no redirect option or create.gsp available. So grails will look first is there any redirect option available and try to redirect create.gsp
Check bellow code changes which will save user id to userInfo table and redirect to index page
So change your usersController
class usersController {
def index() {}
def create() {
def user = new Users(userid: params.uname, password: params.psw).save()
def userInfo = new UserInfo(studentno: params.studno, age: params.age, birth_date: params.birthdate, first_name: params.firstName, last_name: params.lastName, user_id: user.id).save()
if (user && userInfo) {
flash.message = "User created successfully"
redirect action: 'index'
} else {
flash.message = "Problem in user creation"
redirect action: 'index'
}
}
}
And add bellow code to your index.gsp
${flash.message}
There are many ways to redirect to pages. You can use render, redirect, chain, forward ..etc
Please check grails documentation for more information
In Grails for action (non gsp) you need to render something to the client,
otherwise it executes everything inside that action, but returns 404 gsp not found response, if there is no render / redirection statement it consider that action as a gsp but it is not gsp actually, therefore it responds 404.
You could render something data like list / JSON or simple string as follows.
def create() {
//your business logic is here
render "operation performed successfully"
}
First of all what grails version do you use? If the latest one (3.3.4) so this link might be helpful.
Speaking shortly: if you don't specify what to render explicitly - grails tries to find the view to display the result of action execution as:
grails-app/views/<controllerName>/<actionName>.gsp
Looks like you don't have one.
UPD
There are several ways to render action's output in grails controller.
Define explicit content as:
def myAction() {
...
render "Hello World!"
}
That will result in "white screen" with "Hello world!" text in top-left corner.
Another option is to create a gsp view in the conventional location as grails-app/views//.gsp - it will automatically be rendered after action execution if no specifying the render method invocation (like in the sample you've given)
The third option is to specify the model map:
def myAction() {
...
[param1key: param1value, param2key: param2value, ...]
}
The model will be taken into account when rendering your gsp view.
Please read the documentation I gave link to. It's incredibly helpful.

Grails - how to call a controller method from a form

I'm completely new to grails, and I appreciate any help.
This code is in my gsp file:
<g:form action="backfillMachineTags">
<fieldset class="buttons">
<g:submitButton name="create" class="save"
value="${message(code: 'default.button.create.label', default: 'Create')}"/>
</fieldset>
</g:form>
And this code is in my RegressionPoolMachineController.groovy file:
def backfillMachineTags()
{
flash.message = "testing message"
redirect(action: "list")
}
But when I click the submit button on the form, the method is never entered and I get a 404 not found.
message:/pool-manager/regressionPoolMachine/backfillMachineTags
status: The requested resource is not available.
I also tried doing:
<g:form url="[action:'backfillMachineTags',controller:'RegressionPoolMachineController']">
but get a similar 404 not found.
Am I missing a step to connect my form and controller?
Try to use the following:
<g:form controller = "controllerName" action ="actionName" >
<fieldset class="buttons">
<g:submitButton name="create" class="save" value ="${message(code: 'default.button.create.label', default: 'Create')}"/>
</fieldset>
</g:form>
Try adding a "controller" attribute to your form in addition to the "action" attribute. You could use url instead of controller and action, but you would need something like
url="${createLink(controller: "myController", action: "myAction")}" instead of what you've shown here.
For reference: http://docs.grails.org/2.5.6/ref/Tags/form.html
You can also look at the generated HTML in your browser (just view source) and see what is actually being generated on the resulting web page. That's usually pretty helpful for finding out why things aren't going where you want them to!

How to upload files in grails webflow?

I try to build a grails webflow containing a step which has a file upload field in it. Can't find a clear example. How can I do it?
The form looks like this:
<g:form method="POST" action="upload" enctype="multipart/form-data">
<input type="file" name="myFile" />
<input type="submit" value="Upload! " />
</g:form>
The flow looks like this:
def rgdpsRequestFlow = {
chargeCheck{
on("upload"){
println "Hello file upload"
}.to("uploadSuccess")
}
uploadSuccess{
}
}
When I submit the form I get
HTTP Status 404 - /webflowTest/mortgage/upload
It's a little unclear which part you're struggling with. If you need help with the file upload, you may want to try the Grails File Uploader plugin, or otherwise check out this step-by-step tutorial or use the uploadForm tag that James Kleeh has pointed out.
Namely, in the gsp you can add:
<g:uploadForm controller='yourControllerName' action='save'>
<input type='file' name='file'/>
<input type='submit'/>
</g:uploadForm>
Then handle it in the controller:
def save = {
def file = request.getFile('file').inputStream.text
file.transferTo(new File('someLocation/filename'))
}
The problem was I used g:form action attribute.
The correct way to use file upload with webflow is using g:submitButton
Here is the form code that works fine with my webflow:
<g:form method="POST" enctype="multipart/form-data">
<input type="file" name="myFile" />
<g:submitButton class="save" name="upload" value="Upload!"/>
</g:form>

asp.net mvc redirect to action and passing a parameter from user input

I have a page with a input box and a button, when the user clicks the button i want to redirect to a controller action that has as parameter the value of the input box.
<input id="CodProiect" type="text" />
<input id="Cauta" type="button" value="Cauta" onclick="window.location.href='#Url.Action("Cauta", "Componente", new { CodProiect = "param" })';"/>
How can i get the "param" from the input box ?
You could just use a form with a GET method
<form action="#Url.Action("Cauta", "Componente")" method="GET">
<input id="CodProiect" name="CodProiect" type="text" />
<input id="Cauta" type="submit" value="Cauta" />
</form>
The form will add the parameter as part of the query string of the URL e.g. www.yoursite.com/Cauta/Componente?CodProiect=user+entered+value
Value of the Action is prepared at server side and sent to the browser so you cannot have the value at the server when it is a user input.
You can use jquery to change the URL at client side.
Also passing state in an PRG scenario is a common problem in ASP NET MVC. You can either:
Store it temporarily in session
Pass it as a parameter in URL
Use a form.
Form:
<form action="Componente/Cauta">
<input id="CodProiect" type="text" />
<input id="Cauta" type="submit" value="Cauta" />
</form>
Controller:
public ActionResult Cauta(string CodProiect)
{
//Do some stuff
}
More info: http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx
Syntax may be outdated, but you get the point...

Grails action works for GET request, returns 404 for POST request

I'm learning to use Grails and have run into a situation I don't understand when handing what should be a simple form submission.
I have created a controller called 'add' (there is an AddController.groovy source file and an appropriate add/index.gsp view) and have defined a very sparse 'process' action which currently renders a small amount of HTML to verify that the action is being called.
The URL for the process action on the add controller is (not surprisingly) http://localhost:8080/frontend/add/process/.
I would like to submit a very simple form to the process action as a first step towards integrating with some existing Java libraries.
Sending a GET request to http://localhost:8080/frontend/add/process/ causes the process action to be called and the browser to display the relevant simple HTML content.
Sending a POST request to http://localhost:8080/frontend/add/process/ returns a HTTP 404 error.
I appreciate I'm missing some fundamental addition to my application such that the above action works with both GET and POST requests. I had assumed by default the request type would not matter.
I'd be very happy at this stage if I can send a POST request to the appropriate action and have some markup rendered just to demonstrate that things are working.
What fundamentally essentials piece of the puzzle am I missing?
controllers/frontend/AddController.groovy:
package frontend
class AddController {
def index = { }
def process = {
render "<h1>process action being performed</h1>"
}
}
views/add/index.gsp
<html>
<head>
<title>Test View for index action</title>
<meta name="layout" content="main" />
</head>
<body>
<g:form controller="add" action="process">
<label for="title">Title:</label>
<g:textField name="title" id="title" />
<label for="content">Content:</label>
<g:textArea name="content" id="content" />
<g:actionSubmit value="Add" />
</g:form>
</body>
</html>
The <g:actionSubmit /> directive needs an action attribute to indicate the action to be handled. I had assumed the form action would have been sufficient.
I needed to change:
<g:actionSubmit value="Add" />
to:
<g:actionSubmit value="Add" action="process" />

Resources