HTTP Status 400 – Bad Request is being displayed on adding #Valid annotation to my controller - spring-mvc

I'm trying to add a Validation to my form using Hibernate Validator to my project. On submitting the page below is the error message being displayed. But when I remove #Valid annotation from my Controller (UserController.handleLogin) method I'm able to submit the details. Can someone please suggest what am I missing?
UserController.java
#Controller
public class UserController {
#RequestMapping(value = { "/", "/index" })
public String index(Model model) {
model.addAttribute("command", new LoginCommand());
return "index";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String handleLogin(Model model) {
model.addAttribute("err", null);
return "redirect:index";
}
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String handleLogin(#Valid #ModelAttribute("command") LoginCommand cmd, Model model, HttpSession session, Errors error) {
if(error.hasErrors()) {
return "index";
}
try {
User loggedInUser = userService.doLogin(cmd.getLoginName(), cmd.getPassword());
if (loggedInUser == null) {
model.addAttribute("err", "Login failed, enter valid credentials");
return "index";
} else {
if (loggedInUser.getRole().equals(UserService.ROLE_ADMIN)) {
// add user to session
addUserToSession(loggedInUser, session);
return "redirect:admin/dashboard";
} else if (loggedInUser.getRole().equals(UserService.ROLE_USER)) {
// add user to session
addUserToSession(loggedInUser, session);
return "redirect:user/dashboard";
} else {
model.addAttribute("err", "Invalid User Role");
return "index";
}
}
} catch (UserBlockedException e) {
model.addAttribute("err", e.getMessage());
return "index";
}
}
}
LoginCommand.java
public class LoginCommand {
#Size(max = 20, min = 3, message = "Login Name must be between 3 and 20 characters")
private String loginName;
#Size(max = 20, min = 3, message = "Password cannot be empty")
private String password;
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
index.jsp
<s:url var="url_login" value="/login"></s:url>
<f:form action="${url_login}" modelAttribute="command" valign="middle" method="POST">
<table border="1" align="center" width="40%">
<thead>
<tr>
<td colspan="2" valign="middle" align="center">
<h2>Login here</h2></td>
</tr>
</thead>
<tbody>
<tr>
<td align="center">Username: </td>
<td align="center">
<f:input path="loginName" placeholder="Enter your username"/>
<f:errors path="loginName" />
</td>
</tr>
<tr>
<td align="center">Password: </td>
<td align="center">
<f:password path="password" placeholder="Enter your password"/>
<f:errors path="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<f:button>Login</f:button>
New User Registration
</td>
</tr>
</tbody>
</table>
</f:form>

Add Binding result to your method.
BindingResult bindingResult

Related

Trying to update my users password using AddPasswordAsync but passwords always left as null

So i've got 2 tables one for Editing user roles and one fore editing user accounts the roles table allows me to delete and add roles perfectly fine but i'm having trouble with updating passwords. The passwords seem to be getting deleted but not updated with the new one specified.
<br>
<h3>Roles Table</h3>
<table class="table table-striped">
<thead>
<tr> <th>Id</th><th>User Roles</th> </tr>
</thead>
<tbody>
#foreach (var roles in Model.roles)
{
<tr>
<td> #roles.Id</td>
<td> #roles.Name</td>
<td><a class="btn btn-sm btn-danger order-button float-right" asp-page="/ManageRoles" asp-route-id="Delete" asp-page-handler="Delete">Delete Roles </a></td>
</tr>
}
</tbody>
</table>
<form method="post">
<div class="flex">
<div>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
<div class="input-group">
<input type="text" class="form-control" asp-for="#Model.roleName">
</div>
</div>
</form>
<table class="table table-striped" style="margin-top: 100px;">
<thead>
<tr> <th>Id</th><th>User Account</th> </tr>
</thead>
<tbody>
#foreach (var users in Model.users)
{
<tr>
<td> #users.Id</td>
<td> #users.Email</td>
<td><a class="btn btn-sm btn-danger order-button float-right" asp-page="/ManageRoles" asp-route-id="DeleteUser" asp-page-handler="DeleteUser">Delete User </a></td>
<td>
<form method="post" asp-page-handler="Update" asp-route-id="#users.Id">
<div class="input-group">
<input type="text" class="form-control" asp-for="#Model.NewPassword">
<button type="submit" class="btn btn-default">Update Password </button>
</div>
</form>
</td>
</tr>
}
</tbody>
</table>
So heres my Page model class below
{
private readonly RoleManager<IdentityRole> _roleManager;
private readonly UserManager<AppUser> _userManager;
public List <IdentityRole> roles { get; set; }
[BindProperty(SupportsGet = true)]
public string Id { get; set; }
[BindProperty]
public string roleName { get; set; }
public List <AppUser> users { get; set; }
[BindProperty]
public string userId { get; set; }
[BindProperty]
public string NewPassword { get; set; }
public AdminDashboardModel(RoleManager<IdentityRole> roleManager, UserManager<AppUser> userManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
public void OnGet()
{
roles = _roleManager.Roles.ToList();
users = _userManager.Users.ToList();
}
public async Task <IActionResult> OnGetDeleteAsync()
{
var role = await _roleManager.FindByIdAsync(Id);
await _roleManager.DeleteAsync(role);
return RedirectToPage("/AdminDashboard");
}
public async Task<IActionResult> OnPostAsync()
{
if (roleName != null)
await _roleManager.CreateAsync(new IdentityRole(roleName.Trim()));
return RedirectToPage("/AdminDashboard");
}
public async Task<IActionResult> OnGetDeleteUserAsync()
{
var user = await _userManager.FindByIdAsync(Id);
await _userManager.DeleteAsync(user);
return RedirectToPage("/AdminDashboard");
}
public async Task<IActionResult> OnPostUpdateAsync()
{
var user = await _userManager.FindByIdAsync(Id);
await _userManager.RemovePasswordAsync(user);
await _userManager.AddPasswordAsync(user, NewPassword);
return RedirectToPage("/AdminDashboard");
}
}
}
Try it with this bit of code:
public async Task<IActionResult> OnPostUpdateAsync()
{
var user = await _userManager.FindByIdAsync(Id);
var token = await _userManager.GeneratePasswordResetTokenAsync(user)
var result = await _userManager.ResetPasswordAsync(user, token, NewPassword);
//validate result
if(result.Succeeded) {
return RedirectToPage("/AdminDashboard");
}
//handle errors
throw new Exception()
}
You don't actually need to validate the result, but things tend to go sideways. Always better to have error handling.
The generated token validates the action of changing the password against the system. If a user would want to reset their password, because they forgot theirs, you would also need to generate such a token, send it to their email and then let the user choose a new password.
Alternatively you could just use UserManager.UpdatePasswordHash:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.usermanager-1.updatepasswordhash?view=aspnetcore-5.0
var result = await _userManager.UpdatePasswordHash(user, NewPassword, true|false);

Unable to pass view model list in CSHTML to controller

I have a View Model, View, and Controller that works great displaying the data, but I cannot get the data entered in the form to save to the controller. I've tried using a list, array, and a list for the view model.
Here's my view model:
public class AssignedHostData
{
public int HostID { get; set; }
public string HostName { get; set; }
public bool Assigned { get; set; }
[DisplayName("Additional Details")]
[DataType(DataType.MultilineText)]
public string AddDetails { get; set; }
}
Here's the section of my view that displays the data:
<table class="table">
<tr>
#{
int cnth = 0;
List<Support_Web.Models.ViewModels.AssignedHostData> hosts = ViewBag.Hosts;
foreach (var host in hosts)
{
if (cnth++ % 1 == 0)
{
#:</tr><tr>
}
#:<td>
<input type="checkbox"
name="selectedHosts[#cnth].HostID"
id="selectedHosts_[#cnth]_HostID"
value="#host.HostID"
#(Html.Raw(host.Assigned ? "checked=\"checked\"" : "")) />
#host.HostID #: #host.HostName
#:</td>
#:<td>
<input type="text" name="selectedHosts[#cnth].AddDetails" id="selectedHosts_[#cnth]_AddDetails" value="#host.AddDetails" />
#:</td>
}
#:</tr>
}
</table>
And here're the parameters from my Edit controller. The selectedProducts list returns an empty list every time:
public async Task<IActionResult> Edit(int? id, string[] selectedProducts, List<HostCheckListItem> selectedHosts)
My view needed to be formatted this way:
#{
int cnth = 0;
List<Support_Web.Models.ViewModels.AssignedHostData> hosts = ViewBag.Hosts;
for (int i = 0; i < hosts.Count; i++)
{
<tr>
<td>
<input type="checkbox"
name="selectedHosts[#i].HostID"
value="#hosts[#i].HostID"
#(Html.Raw(hosts[#i].Assigned ? "checked=\"checked\"" : "")) />
#hosts[#i].HostName
</td>
<td>
<input type="text" name="selectedHosts[#i].AddDetails" value="#hosts[#i].AddDetails" />
</td>
</tr>}
}
If you want to transfer the modified model data list in the view to
the controller, you can use "asp-for" to bind in the form.
Please refer to the following for details:
public class ProductController : Controller
{
private readonly MydbContext _context;
public ProductController (MydbContext context)
{
_context = context;
}
public IActionResult Index()
{
ViewBag.Hosts = _context.AssignedHostData.ToList();
return View();
}
public async Task<IActionResult> Edit(List<AssignedHostData> Hosts)
{
List<AssignedHostData> selectedHosts = Hosts.Where(x => x.Assigned == true).ToList();
return View();
}
}
Edit.cshtml:
<form asp-controller="Product" asp-action="Edit" method="post">
<table class="table">
<tr>
#{
int cnth = 0;
List<WebApplication_core.Models.AssignedHostData> Hosts = ViewBag.Hosts;
for (int i = 0; i < Hosts.Count; i++)
{
<tr>
<td>
<input id="Hidden1" type="hidden" asp-for="#Hosts[i].HostID" />
<input type="checkbox" asp-for="#Hosts[i].Assigned" />
#Hosts[i].HostName
<input id="Hidden2" type="hidden" asp-for="#Hosts[i].HostName" />
</td>
<td>
<input type="text" asp-for="#Hosts[i].AddDetails" />
</td>
</tr>
}
}
</table>
<input id="Button1" type="submit" value="Edit" />
</form>
Here is the debug result:

Radio button list using editor templates for merging contacts

I am trying to display a form for merging two contacts in ASP.net MVC 5.
The form should look like this where each row holds a radio button group consisting of 2 options:
The form shows up just fine, and the radio groups work (I can select each group). However, when the model is posted back to the server, the Values list is empty (not preserved). I would like to get both the selected id but of course also the actual text value back in the controller. I prefer to do this using Editor Templates and if possible without for loops.
The current results (Values = null):
EDIT to respond to comments: I would prefer not to re-fetch the values in the controller again, because it results in a call to a web service. I have tried some variants of HiddenFor without results.
My models look like this:
public class Contact
{
public List<ContactRow> Rows { get; set; }
public Contact()
{
this.Rows = new List<ContactRow>();
this.Rows.Add(new ContactRow("First Name", "Homer", "Homie"));
this.Rows.Add(new ContactRow("Last Name", "Simpson", "Simson"));
this.Rows.Add(new ContactRow("Email", "mail1", "mail2"));
this.Rows.Add(new ContactRow("Company Phone", "Phone1", "Phone2"));
this.Rows.Add(new ContactRow("Mobile Phone", "Mobile1", "Mobile2"));
}
}
public class ContactRow
{
public int Selection { get; set; }
public string Label { get; set; }
public List<ValueSet> Values { get; set; }
public ContactRow(string Label, string LeftValue, string RightValue, int Selection = 0)
{
if (LeftValue== null) LeftValue= "";
if (RightValue== null) RightValue= "";
this.Label = Label;
this.Selection = Selection;
this.Values = new List<ValueSet>(2);
this.Values.Add(new ValueSet() { ID = 0, ValueText = LeftValue});
this.Values.Add(new ValueSet() { ID = 1, ValueText = RightValue});
}
public ContactRow() { }
}
public class ValueSet
{
public int ID { set; get; }
public string ValueText { set; get; }
}
The Controller:
public ActionResult Index()
{
Contact model = new Contact();
return View(model);
}
public ActionResult MergeContacts(Contact model)
{
return RedirectToAction("Index");
}
And the views:
Index.cshtml
#model RadioTest.Models.Contact
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm("MergeContacts", "Home", FormMethod.Post, new { encType = "multipart/form-data", id = "contactDetailsForm", name = "contactDetailsForm" }))
{
<div>
<table class="table" width="100%">
<tr>
<th style="text-align:left">Label</th>
#*<th style="text-align:right">R1</th>*#
<th style="text-align:left">
Left Value
</th>
#*<th style="text-align:right">R2</th>*#
<th style="text-align:left">
Right Value
</th>
</tr>
#Html.EditorFor(model => model.Rows)
</table>
<input type="submit" />
</div>
}
Editor Template for ContactRow:
ContactRow.cshtml
#model RadioTest.Models.ContactRow
<tr>
<td style="text-align:left">
#Html.DisplayFor(model => model.Label)
</td>
#foreach (var v in Model.Values)
{
<td style="text-align:left">
#Html.RadioButtonFor(model => model.Selection, v.ID) #v.ValueText
</td>
}
</tr>
#Html.HiddenFor(model => model.Label)
Just change your foreach to for:
#model MVCApp.Controllers.ContactRow
<tr>
<td style="text-align:left">
#Html.DisplayFor(model => model.Label)
</td>
#for (int i = 0; i < Model.Values.Count; i++)
{
<td style="text-align:left">
#Html.RadioButtonFor(model => model.Selection, Model.Values[i].ID) #Model.Values[i].ValueText
#Html.HiddenFor(model => Model.Values[i].ID)
#Html.HiddenFor(model => Model.Values[i].ValueText)
</td>
}
</tr>
#Html.HiddenFor(model => model.Label)

Validators not supporting for second pojo Address in spring mvc

Validation is working fine for User class but not for address class
Registration.java
package com.semanticbits.controller;
import com.semanticbits.pojo.Address;
import com.semanticbits.pojo.User;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping("/register")
public class RegistrationController {
#RequestMapping(method = RequestMethod.GET)
public String showRegistrationForm(ModelMap map){
User user=new User();
user.setAddress(new Address());
map.addAttribute("user", user);
return "register";
}
//reference data
#ModelAttribute("genderList")
public List<String> showGenderOnForm(){
List<String> genderList=new ArrayList<>();
genderList.add("Select gender");
genderList.add("Male");
genderList.add("Female");
return genderList;
}
#RequestMapping(method = RequestMethod.POST)
public String processRegistrationForm(#ModelAttribute("user") User user, BindingResult result) {
validator.validate(user, result);
//validator.validate(user.getAddress(), result);
if (result.hasErrors()) {
return "register";
}
return "welcome";
}
}
Address.java
package com.semanticbits.pojo;
import javax.persistence.Embeddable;
import org.springmodules.validation.bean.conf.loader.annotation.handler.NotBlank;
import org.springmodules.validation.bean.conf.loader.annotation.handler.Size;
#Embeddable
public class Address {
#NotBlank(message = "Please enter city")
private String city;
#NotBlank(message = "Please enter state")
private String state;
#NotBlank(message = "Please enter zip code")
#Size(max = 6,min = 6,message = "Zip code should be of 6 digits only")
private int zipCode;
//setters and getters
}
User.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.semanticbits.pojo;
import com.semanticbits.pojo.Address;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springmodules.validation.bean.conf.loader.annotation.handler.Length;
import org.springmodules.validation.bean.conf.loader.annotation.handler.Max;
import org.springmodules.validation.bean.conf.loader.annotation.handler.Min;
import org.springmodules.validation.bean.conf.loader.annotation.handler.NotBlank;
#Entity
#Table
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int userId;
#NotBlank(message = "Please enter username")
#Length(min = 6,message ="Please enter minimum six characters" )
private String username;
#NotBlank(message = "Please enter password")
private String password;
#NotBlank(message = "Please enter your first name")
private String firstName;
#NotBlank(message ="Please enter your last name")
private String lastName;
#Min(value=18,message = "Age should be greater than 18")
#Max(value=100,message="Age should be less than 99")
private int age;
private String gender;
#Embedded
private Address address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
register.jsp
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%#taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login here</title>
<link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
<style>
.form-error-message{ font-weight: bold; color: red; }
.errorblock {
color: #000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
<body>
<div class="container">
<div class="modal-form"/>
<h1>Registration form</h1>
<form:form commandName="user" action="register.htm" method="POST">
<form:errors path="*" cssClass="errorblock" element="div" />
<table>
<tr>
<td> Username :</td>
<td><form:input path="username"/></td>
<td><form:errors path="username" cssClass="form-error-message"/>
</tr>
<tr>
<td>Password :</td>
<td><form:input path="password"/></td>
<td><form:errors path="password" cssClass="form-error-message"/>
<tr>
<tr>
<td>Confirm Password :</td>
<td><input type="password" name="confirmPassword"/></td>
<tr/>
<tr>
<td>First Name :</td>
<td><form:input path="firstName"/></td>
<td><form:errors path="firstName" cssClass="form-error-message"/></td>
<tr/>
<tr>
<td>Last Name :</td>
<td><form:input path="lastName"/></td>
<td><form:errors path="lastName" cssClass="form-error-message"/></td>
<tr/>
<tr>
<td>Age :</td>
<td><form:input path="age"/></td>
<td><form:errors path="age" cssClass="form-error-message"/></td>
<tr/>
<tr>
<td>Gender :</td>
<td><form:select items="${genderList}" path="gender"/></td>
<tr/>
<tr>
<td>City :</td>
<td><form:input path="address.city"/></td>
<td><form:errors path="address.city" cssClass="form-error-message"/></td>
<tr/>
<tr>
<td>State :</td>
<td><form:input path="address.state"/></td>
<td><form:errors path="address.state" cssClass="form-error-message"/></td>
</tr>
<tr>
<td>Zip Code :</td>
<td><form:input path="address.zipCode"/></td>
<td><form:errors path="address.zipCode" cssClass="form-error-message"/></td>
</tr>
<tr>
<td> <input type="checkbox" name="rememberme"/>Remember Me</td>
<td><input type="submit" class="btn-medium btn btn-info" value="Login"/></td>
</tr>
</form:form>
</div>
</div>
<script src="js/bootstrap.min.js"></script>
</body>
</html>
Since you're using the JSR 303 annotations, try annotating the nested Address property in the User class as #Valid
User.java
#Embedded
#Valid
private Address address;
In the controller, you can also annotate your User ModelAttribute as #Valid so that validation will take place automatically.
RegistrationController.java
#RequestMapping(method = RequestMethod.POST)
public String processRegistrationForm(#ModelAttribute("user") #Valid User user, BindingResult result) {
if (result.hasErrors()) {
return "register";
}
return "welcome";
}
Alternatively you can write a custom validator which can validate both the User and nested Address object.
Here's a post with a worked example describing validation of embedded objects using #Valid http://www.openscope.net/2010/02/08/spring-mvc-3-0-and-jsr-303-aka-javax-validation/

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name

I'm getting the following error when I try to access a Spring MVC form I created:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'roomSelection' available as request attribute
Here's the controller:
#Controller
#RequestMapping("/welcome")
public class RoomSelectionListController {
final private static String WELCOME_VIEW = "welcome";
final private static String SUCCESS_VIEW = "chatroom";
// Value will be injected.
private ChatRoomRegistryService chatRoomRegistryService = null;
private RoomSelectionValidator roomSelectionValidator = null;
private static Logger logger = Logger.getLogger(RoomSelectionListController.class);
public ChatRoomRegistryService getChatRoomRegistryService() {
return chatRoomRegistryService;
}
#Autowired
public void setChatRoomRegistryService(ChatRoomRegistryService chatRoomRegistryService) {
this.chatRoomRegistryService = chatRoomRegistryService;
}
#Autowired
public RoomSelectionListController(RoomSelectionValidator roomSelectionValidator) {
this.roomSelectionValidator = roomSelectionValidator;
}
#ModelAttribute("roomSelection")
protected RoomSelection getRoomSelection() {
logger.debug("Creating a RoomSelection instance");
return new RoomSelection();
}
#ModelAttribute("chatRoomList")
protected List<ChatRoom> populateChatRoomList(HttpServletRequest request) throws Exception{
logger.debug("Creating a chatRoomList");
User user = (User) request.getSession().getAttribute("userLoggedIn");
List<ChatRoom> chatRoomsForUser = chatRoomRegistryService.getChatRoomsForUser(user);
return chatRoomsForUser;
}
#RequestMapping(method = RequestMethod.POST)
protected String processSubmit(#ModelAttribute("roomSelection") RoomSelection roomSelection, BindingResult result, ModelMap model, HttpServletRequest request, HttpServletResponse response) throws Exception {
roomSelectionValidator.validate(roomSelection, result);
if (result.hasErrors()) {
return WELCOME_VIEW;
} else {
model.addAttribute("chatroom", roomSelection.getChatRoom());
User user = (User) request.getSession().getAttribute("userLoggedIn");
model.addAttribute("userLoggedIn", user);
return SUCCESS_VIEW;
}
}
#RequestMapping(method = RequestMethod.GET)
protected String initForm(ModelMap model) throws Exception {
logger.debug("Inside RoomSelectionListController.initForm()");
RoomSelection roomSelection = new RoomSelection();
model.addAttribute("roomSelection", roomSelection);
return WELCOME_VIEW;
}
}
And here's my form section of JSP:
<form:form id="joinForm" modelAttribute="roomSelection" method="POST">
<table>
<legend><spring:message code="welcome.chatroom.list.lbl" /></legend>
<tr>
<td>
<form:select id="selectChatRoomList" path="chatRoomId" size="7" cssClass="chatRoomList">
<form:options items="${chatRoomList}" itemValue="chatRoomId"
itemLabel="chatRoomName" />
</form:select>
</td>
</tr>
<tr>
<td><form:errors path="chatRoomId" cssClass="advchatError" /></td>
</tr>
<tr>
<td>
<a id="submitJoinChatRoom" href="javascript:void(0)" class="green-button" onclick="$('#joinForm').submit();">
<span class="green-button-outer">
<span class="green-button-inner">
<div class="joinRoomButtonWidth"><spring:message code="welcome.joinchat.lbl" /></div>
</span>
</span>
</a>
</td>
</tr>
</table>
</form:form>
This seems to be a common beginner issue but I can't seem to figure out what I'm doing wrong.
Any ideas?
Thanks,
Steve
#SteveN
I just took your code and made it simple (meaning removed those service dependencies and had just a get method alone to figure out the issue). It works like charm. May be you can also make your code simple and then keep adding things once you have a working thing in place. Here is my code
Controller
#Controller
#RequestMapping("/welcome")
public class RoomSelectionListController {
final private static String WELCOME_VIEW = "welcome";
#RequestMapping(method = RequestMethod.GET)
protected String initForm(ModelMap model) throws Exception {
RoomSelection roomSelection = new RoomSelection();
roomSelection.setRoomName("MyRoom");
model.addAttribute("roomSelection", roomSelection);
return WELCOME_VIEW;
}
}
RoomSelection bean
public class RoomSelection {
private String roomName;
public void setRoomName(String roomName) {
this.roomName = roomName;
}
public String getRoomName() {
return roomName;
}
}
welcome.jsp
<form:form id="joinForm" modelAttribute="roomSelection" method="POST">
<table>
<tr>
<td>Room Name : </td>
<td>
<form:input path="roomName"/>
</td>
</tr>
</table>
</form:form>
My Output
The only place which i have a suspect in your code is in your post method, when the validation fails you are setting the model view as WELCOME_VIEW, i wonder whether during this time you #ModelAttribute will be called and will it add the roomSelection attribute or not. Again its a guess.

Resources