I have post mapping for URL: "/bank/addnew" My controller looks like:
Upon submission the form is submitted to "http://127.0.0.1:8082/banks/%20/banks" However, I need it to go to "http://127.0.0.1:8082/banks/addnew". Thanks for the Help!
#Controller
public class BankController {
#Autowired private BankService bankService;
#GetMapping("/banks")
public String bankList() {
return "bank/bank_list";
}
#PostMapping(value="/banks/addnew")
public String addNew(Bank bank) {
bankService.save(bank);
return "redirect: /banks";
}
}
And my template:
<form method="POST" action="#" th:action="#{/banks/addnew}" >
<div class="form-group">
<label for="recipient-name" class="col-form-label">Bank Name:</label>
<input type="text" class="form-control" id="recipient-name" name="name">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
The Post Method was actually working okay. I checked it by printing the Model object inside the target controller. However, it was being submitted to the database a NULL value because I didn't initialize getters and setters for my Model. Finally, there was a space in the return string, thus I removed it.
The controller Should have a return statement with no space.
return "redirect:/banks";
Related
I am using Remote Attribute validation
The method is invoked successfully on textchange event. However, the parameters in the action method of the controller does not get the value of the field.
Here is the Action Method in the HomeController.cs. When invoked the Name parameter remains null. I will be pleased if someone solve this problem
[AcceptVerbs("Get", "Post")]
public async Task<ActionResult> IsExist(string Name)
{
List<Keywords> keywords = new List<Keywords>();
HttpClient client = _api.Initial();
HttpResponseMessage res = await client.GetAsync("api/Keywords");
if (res.IsSuccessStatusCode)
{
var result = res.Content.ReadAsStringAsync().Result;
keywords = JsonConvert.DeserializeObject<List<Keywords>>(result);
}
if (keywords.FirstOrDefault(x => x.Name == Name) == null)
{
return Json(false);
}
else
{
return Json(true);
}}
Here is the Model
public partial class Keywords
{
public int Id { get; set; }
[Display(Name = "Name of Keyword")]
[Required]
[Remote(action: "IsExist",controller: "Home", ErrorMessage = "Keyword already present!")]
public string Name { get; set; }}
Here is the razor page in which I want to implement validation
#page
#model Consumer.Pages.Keyword.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Keywords</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Keywords.Name" class="control-label"></label>
<input asp-for="Keywords.Name" class="form-control" />
<span asp-validation-for="Keywords.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Keywords.Department" class="control-label"></label>
<select asp-for="Keywords.DepartmentId" class="form-control" asp-items="ViewBag.Department"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
I found the solution. It is to
Remove partial in the model class definition.
Replace in the Razor Page
<input asp-for="Keywords.Name" class="form-control" />
with
<input asp-for="Keywords.Name" name="Name" class="form-control" />
The [Remote] attribute is all but useless. There's a long-standing problem from the ASP.NET MVC days that migrated its way into ASP.NET Core unabated, as well. Namely, the action that handles the remote must take a param that matches the input name of what what's being validated. In other words, your action takes a param, name, but what's being sent to it is Keywords.Name, which cannot bind to name. You'd have to do something like:
public async Task<ActionResult> IsExist(Keywords keywords)
And then, then the value will be available via keywords.Name. This obviously makes the usage highly dependent on the particular implementation, so if there's a situation with a different input name like Foo.Keywords.Name, then you'd need an entirely different action, to match that binding, and basically duplicate the logic (though you could factor out the majority the logic into some common method all the actions could utilize).
Long and short, you're probably better off just handling this yourself manually. Just bind to the input event on the name input, and then call your method via AJAX. Then you can explicitly control the key that's sent in the request body, such that it will always match your action. Just note that you'll also want to debounce sending that AJAX request so that it only happens every few keystrokes or so. Otherwise, you're going to hammer your action.
I am getting below warning as
WARN [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (default task-1) Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
I have already set the method as POST but still I'm getting the above error. I'm getting this warning message for my delete controller all other CRUD operations are working fine, except delete.
Please find below code
Controller mapped deleteproducts :
#RequestMapping(value="/deleteproducts", method= RequestMethod.POST)
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
here's my jsp view:
<body>
<form id="update product form" action="${pageContext.request.contextPath}/deleteproducts" method="post" role="form" style="display: none;">
<div class="form-group row">
<label for="product Id" class="col-sm-2 col-form-label">Id</label>
<div class="col-sm-10">
<input type="text" name="productId" class="form-control" id="productid" placeholder="Enter the product Id you want to delete">
</div>
</div>
</form>
</body>
DAOimplementation for delete Method call:
public boolean deleteProduct(int productId)
{
boolean b = true;
try
{
sess.beginTransaction();
Products p = (Products)sess.load(Products.class, new Integer(productId));
sess.delete(p);
sess.getTransaction().commit();
}catch(Exception ex)
{
sess.getTransaction().rollback();
b = false;
}
return b;
}
can some one now tell me what changes should I make in my code to fix this ?
Thank you!
edit 1:
#DeleteMapping(value="/deleteproducts/{productId}")
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
}
still getting a warning as:
WARN [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (default task-1) Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
I don't understand #RequestMapping(value="/deleteproducts", method= RequestMethod.POST)
what do you mean by this? You are making a RequestMapping want to delete a record and method is POST?
I would suggest please follow the standard way of development. If you want to delete DeleteMapping, for POST use PostMapping and to retrieve some information you can use GetMapping.
Ideally, it should be
#DeleteMapping("/deleteproducts/{id}")
public void deleteStudent(#PathVariable long id) {
deleteproductsRepository.deleteById(id); or some CRUD logic to delete
}
You can refer to this link for better understanding REST
AS i think request form going to GET Method you can try javascript to submit form with function call.
Please find below code :
<form id="update product form" action="${pageContext.request.contextPath}/deleteproducts" method="POST">
<div class="form-group row">
<label for="product Id" class="col-sm-2 col-form-label">Id</label>
<div class="col-sm-10">
<input type="text" name="productId" class="form-control" id="productid" placeholder="Enter the product Id you want to delete">
</div>
<div class="col-sm-10">
<input type="button" value="submit" onclick="javascript:formSubmit()" name="submit" ></a>
</div>
</div>
</form>
<script>
function formSubmit() {
if(!isEmpty(document.from.productId.value)){ //even you can validate values in productId
document.form.method='POST';
document.form.action='/deleteproducts';
document.form.submit();
}
)
<script>
After writing the below code
#DeleteMapping(value="/deleteproducts/{productId}")
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
}
After this instead of running on a normal browser, try running it on a REST API. I tried it on POSTMAN API and I don't get the error. Look at the below image
I am working on webapp using spring mvc + hibernate. I am getting a warning as
WARN [org.springframework.web.servlet.PageNotFound] (default task-1) No mapping for GET /ProjectFE/deleteproducts/
here's my code for Controller mapped deleteproducts:
#DeleteMapping(value="/deleteproducts/{productId}")
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
}
jsp view:
<body>
<form id="update product form" action="${pageContext.request.contextPath}/deleteproducts" style="display: none;">
<div class="form-group row">
<label for="product Id" class="col-sm-2 col-form-label">Id</label>
<div class="col-sm-10">
<input type="text" name="productId" class="form-control" id="productId" placeholder="Enter the product Id you want to delete">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</form>
</body>
DAOImplementation for delete method call:
public boolean deleteProduct(int productId)
{
boolean b = true;
try
{
sess.beginTransaction();
Products p = (Products)sess.load(Products.class, new Integer(productId));
sess.delete(p);
sess.getTransaction().commit();
}catch(Exception ex)
{
sess.getTransaction().rollback();
b = false;
}
return b;
}
can this issue be occurring because of the /{productId} part ? Please some one help!!
Thankyou.
First, create a controller to go to deleteproduct.jsp page. So write a controller like
#GetMapping(value="/delete")
public String deleteProduct() {
return "deleteproducts";
}
So hit /delete to got to page then do as you want.
Change your #DeleteMapping to #GetMapping. And use #RequestParam instead of #PathVariable. So your controller will be like
#GetMapping(value="/deleteproducts")
public String deleteProduct(#RequestParam(value="productId")String productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(Integer.parseInt(productId));
if(b)
return "success";
else
return "deleteproducts";
}
And write your form like
<form id="searchForm" class="form-horizontal" action="${pageContext.request.contextPath}/deleteproducts">
<div class="input-group">
<input name="productId" placeholder="Delete product with id" class="form-control productId"
type="text">
<span class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</form>
You are trying to get an endpoint which doesn't exists. Why?
When you specify an endpoint /some_end_point and you trying to reach it with http protocol, it will expect you to specify the request method (GET / POST / PUT / DELETE / etc...).
When you have those 2 parameters /some_end_point + POST you need to map it in your server side like this -> #PostMapping("/some_end_point").
If the client (or another server) will try to reach /some_end_point + GET it will fail because it doesn't exists, only /some_end_point + POST exists, therefor you have to add another endpoint which will be #GetMapping("/some_end_point") and so on.
You are sending a GET request,
but you annotated with #DeleteMapping - which expects a DELETE request.
I am trying to create a form with 3 fields within the class LoginForm: usuario, senha, msgLogin.
I receive the fields usuário and senha from the input boxes and then I try to redirect to the same page with the same fields plus the field MsgLogin. But I've not been able to update the msgLogin field and I don't understand why.
These are the code:
HTML:
<form id="frmLogin" class="form col-md-12" action="#" th:action="#{/login}" th:object="${loginForm}" method="post">
<div class="form-group">
<label for="usuario" class="col-md-1">Usuário: </label>
<input type="text" id="usuario" placeholder="Email" th:field="*{usuario}"/>
</div>
<div class="form-group">
<label for="senha" class="col-md-1">Senha: </label>
<input type="password" id="senha" placeholder="senha" th:field="*{senha}"/>
</div>
<div class="row">
<button id="entrar">Entrar</button>
</div>
<div class="row">
<div id="msgLogin"></div>
<p th:text="${loginForm.msgLogin}" />
</div>
</form>
The Controller:
#RequestMapping("/")
public String init(#ModelAttribute LoginForm loginForm) {
Logger.getAnonymousLogger().info("Tela Inicial.");
return "home";
}
#PostMapping("/login")
public ModelAndView entrar(LoginForm loginForm) throws IOException {
Logger.getAnonymousLogger().info("Entrando no Internet Banking.");
service.login(usuario, senha);
ModelMap model = new ModelMap();
loginForm.setMsgLogin("I want to update that value!");
model.addAttribute("loginForm", loginForm);
return new ModelAndView("redirect:/", model);
}
Class using Lombok:
#Getter
#Setter
public class LoginForm {
private String usuario;
private String senha;
private String msgLogin;
}
A redirect send a 302 HTTP status back to the browser to resubmit using a new url, so it resubmits the same two fields to the new url. There's no expectation of payload data in the 302 response.
In your Controller, change the last line in your entrar method to: return new ModelAndView("/login", model);
There are a lot of similar questions to this, I have looked at them but still couldn't figure out what my problem is. Would really appreciate help with this.
This is my controller:
#RestController
#RequestMapping(value = "/game")
public class YatzyController {
#Autowired
private Games games;
#RequestMapping(value = "/{DiceDTO}", method = RequestMethod.POST)
public GameState putGameState(#ModelAttribute("DiceDTO") DiceDTO diceDTO) {
return null;
}
And this is my HTML:
<form method="post" enctype='application/json' action="/game">
<button type="button" onclick="rollDice()">Roll dice</button>
<div>
<input type="text" id="dice1" disabled>
<input type="checkbox" id="keepdice1" value="Keep">
</div>
<div>
<input type="text" id="dice2" disabled>
<input type="checkbox" id="keepdice2" value="Keep">
</div>
<input type="submit">
</form>
Configuration class:
#Configuration
public class YatzyConfiguration {
#Bean
public Games games(){
return new Games();
}
}
Posting to /game
You don't need value = "/{DiceDTO}" in #RequestMapping annotation, because Spring considers it as path's part. So Spring actually maps POST request to /game/somenting path in your case.