Passing parameters to httpPost method in a controller in MVC - asp.net

I have a controller with this method
[HttpPost]
public ActionResult AssociateCaseDetails(string btnSubmit, string navigate)
{
................................
................................
}
In the view i had an input like
<input type="submit" class="backdetails" value="BACK" name="btnSubmit" />
When i clicked on that button the btnSubmit value was BACK, so i thought of creating a similar input which will call that method
<input type="submit" class="submit" value="SAVE" name="btnChangeStatus" />
When i click this the AssociateCaseDetails is getting called but the btnSubmit is having null as value
What have i done wrong here?

Your post method has a parameter named btnSubmit, so the first submit button works because it has the attribute name="btnSubmit". The second does not work because it has name="btnChangeStatus". Change the second button to have the same name attribute (name="btnSubmit") so that it will be bound to your parameter.

Related

Razor Pages - Returning Model Value

I'm new to Razor pages and having trouble with model binding back to the view.
I'm using VS2019 version 16.0.4.
This is my PageModel:
public class IndexModel : PageModel
{
[BindProperty]
public int PageIndex { get; set; }
public IActionResult OnPost()
{
PageIndex++;
return Page();
}
}
And my View:
#page
#model IndexModel
<form method="post">
<div class="form-group">
<label asp-for="PageIndex"></label>
<input asp-for="PageIndex" class="form-control" />
<span class="text-danger" asp-validation-for="PageIndex"></span>
<button type="submit" class="btn btn-primary">Increment</button>
</div>
</form>
I would expect the value displayed in the input control to be incremented on each click - but it remains at zero. The binding into the controller seems to work ok. If I enter a value of "5" and click the button then a breakpoint shows me that a value of 5 is received before being incremented to 6. However, the incremented value does not get reflected back to the view.
Where did I go wrong?
Model binding takes values from the HTTP request and binds them to handler method parameters or PageModel properties. It is not two-way, and does not then bind those values back to the controls where the values originated.
You need to explicitly set the value attribute of the input to see the behaviour that you expect:
<input asp-for="PageIndex" value="#Model.PageIndex" />

Button calling different servlet code in html form

I am bit new to Java web programming
I have two buttons(Test connection and Execute) in an html form and the form action is a servlet. How can I differentiate the action in the servlet based on which button is clicked.
Thanks
In the HTML:
<input type='submit' name='submitButton' value='Test connection' />
<input type='submit' name='submitButton' value='execute' />
In the servlet:
String clickedButtonValue = request.getParameter("submitButton");
if("Test connection".equals(clickedButtonValue))
{
...
}
else if("execute".equals(clickedButtonValue))
{
...
}
else ...
The reason this works: With both submit buttons sharing the same name attribute, the browser will only send the value of the one that was clicked.

Spring initBinder StringTrimmerEditor - exclude some fields

In my current application by using init binder-StringTrimmerEditor we are nullifying all the values which are empty from the view/templates. But now I want to remove one field(movielist) from being nullified as this particular field when I edit the form i.e., remove all the values in the movie-list and click save button controller is getting null value instated of empty string. I want it to be as empty String instead of null value.
How do I exclude the movielist from being nullified.
<form action="#" th:object="${CustomerForm}" th:action="#{customer/save}" method="post">
<input type="hidden" th:field="*{id}"/>
<textarea th:field="*{movieList}"></textarea>
<div class="modal-footer">
<input class="btn-submit" type="submit" value="Save"/>
</div>
</form>
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(emptyAsnull:true));
}
You can look at this question
. You might have to set the allowed fields value for your databinder which will also solve a potential security concern.

Form Submission on Enter Press

I have a form in my ASP .NET project that takes the users input, and appends it to a URL to search a wiki. The form works perfectly when you enter in a search term, and click the 'search' button, however when you type into the input box and hit enter, the page refreshes and the box clears.
my html
<form>
<label id="sideBarLabel"> Services
<input type="text" placeholder="Search Wiki: e.g. E911" name="queryString" id="query-string" />
</label>
Search Wiki
</form>
my js
function searchWiki(){
var siteQuery = $('#query-string').val();
window.location.href = "/dosearchsite.action?queryString=" + siteQuery;
}
Can anyone help ?
Your searchWiki() js method is only called when the evenement onclick is raised on your button, but not when your form is submitted.
There is several ways to achieve what you want:
Add a js method to catch the onsubmit event of your form:
$("form").on("submit", searchWiki());
Or add a tag on your form:
<form onsubmit="searchWiki()">
Or specify the action attribute on your form:
<form action="/dosearchsite.action">
Note that in ASP.NET, the ModelBinder will link your form inputs to your controller action parameters, using the name attribute of the inputs. That means that you should not specify them in the url yourself.
You should also declare your form using Html.BeginForm or Ajax.BeginForm if you want your form to be submitted by ajax.
#Html.BeginForm("ActionName", "ControllerName")
{
<label id="sideBarLabel">Services
<input type="text" placeholder="Search Wiki: e.g. E911" name="queryString" id="query-string" />
</label>
<input type="submit" class="button" value="Search Wiki"/>
}
This will call searchWiki when you press enter.
$('#query-string').keypress(function(event) {
if (event.keyCode == 13) {
searchWiki();
event.preventDefault();}});

Spring 3.1 MVC and Security: both login and registration form (multiple forms) on same page get submitted

I'm using Spring (3.1), Spring MVC (3.1) and Spring Security (3.0) in combination and I've put together a single JSP page that has two forms on it; One is a form to login and the other is a form to register (i.e. create a new user).
For the register form, I use the Spring form tags, backed up by a controller to handle the request but for the login form I don't bother with the Spring form tags as I don't believe they're needed. There is also no controller that I need to write to handle the form submission as Spring Security takes care of authenticating so long as the request is submitted to j_spring_security_check.
The register form is working fine but the login form is a problem. It seems that when I click the submit button on the login form, the registration form is also submitted, or at least Spring thinks I'm trying to submit that form. Here is the JSP:
<form id="loginform" method="POST" action="<c:url value='j_spring_security_check'/>">
<label for="existing_email">Email:</label>
<input name="j_username" id="existing_email" type="text" value="${SPRING_SECURITY_LAST_USERNAME}" />
<label for="existing_password">Password:</label>
<input name="j_password" id="existing_password" type="password" />
<input id="login-form-submit" type="submit" value="Sign in" />
</form>
<form:form id="registrationform" modelAttribute="user" method="POST" action="register">
<form:label path="username" for="email">Email:</form:label>
<form:input path="username" name="username" id="email" type="text" />
<form:errors path="username" cssClass="formError" />
<form:label path="password" for="password">Password:</form:label>
<form:input path="password" name="password" id="password" type="password" />
<form:errors path="password" cssClass="formError" />
<input id="registration-form-submit" type="submit" value="Sign up" />
</form:form>
Notice that form tags for the input of type submit are not present and this seems to be a normal thing to do in the examples I've seen. Adding form tags to the submit button I guess doesn't make sense as it doesn't map to anything on the target object (user in this case).
When I click the "Sign in" button I get the following exception:
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/project1] threw exception [An exception occurred processing JSP page /WEB-INF/views/registration.jsp at line 29
28: <form:form id="registrationform" modelAttribute="user" method="POST" action="register">
29: <form:label path="username" for="username">Username:</form:label>
30: <form:input path="username" name="username" id="username" type="text" />
31: <form:errors path="username" cssClass="formError" />
32:
Stacktrace:] with root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
This I recognise from cases where you forget to include the modelAttribute attribute in form:form, but of course I don't want to submit this form to my controller.
I have a feeling there is a mistake I'm making or a simple solution. Can anyone recommend a way around this or perhaps a different approach?
Here is the controller method that handles requests to register in case that's needed:
#RequestMapping(value = "**/register", method = RequestMethod.POST)
public String registerUser(#ModelAttribute("user") #Validated User user, BindingResult errors, ModelMap model) {
if (errors.hasErrors()) {
return "registration";
}
// Other stuff then...
return "profile"
}
If you are using "user" modelAttribute in form tag then a non-null request attribute must be present with name "user".
One way to add that in request attribute is what you did in your answer above. Other ways are:
(1) Add in ModelMap:
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(ModelMap model) {
model.addAttribute("user", new User());
model.addAttribute("error", "true");
return "registration";
}
(2) Add in request scope (Using WebRequest or HttpServletRequest):
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(ModelMap model, WebRequest webRequest) {
webRequest.setAttribute("user", new User(), WebRequest.SCOPE_REQUEST);
model.addAttribute("error", "true");
return "registration";
}
(3) Use #ModelAttribute on method:
#ModelAttribute("user")
public User user() {
return new User();
}
Please also see Using #ModelAttribute on a method and Using #ModelAttribute on a method argument
Also note that you don't have to use type attribute. See form:input and form:password.
I think the problem is specifically when a login fails and the same page is served up, albeit on a different URL path and so through a different controller method. Therefore my original suspicion that the issue is that both forms are submitted may be something of a red herring, though I still don't fully understand what's going on and that may yet have something to do with it. In any case, this is what corrected the problem for me:
I had a controller method that originally looked like this:
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(ModelMap model) {
model.addAttribute("error", "true");
return "registration";
}
In the Spring Security context I specify /loginfailed as the path to go to by default if a login attempt fails. This is where it seems the user object is needed so if I alter the signature as follows it all works:
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(#ModelAttribute("user") User user, BindingResult errors, ModelMap model) {
model.addAttribute("error", "true");
return "registration";
}
Any comments/clarification welcome from others.

Resources