How to pass #ModelAttribtue to Controller and call POST method to insert the data in spring mvc using ajax call - ajax

I am using jstl and I need to get back the id upon insertion to jsp from controller. To achieve that I am using ajax and I am unable to pass the modelAttribute of the form.
JSP
<form:form method="POST" action="addCountry.html" name="form" modelAttribute="countryMaster" id="addCountryForm">
<div class="box-body">
<div class="row">
<div class="col-md-6">
<div class="form-group has-feedback" id="countryNameDiv">
<form:label path="countryName" for="countryName">Country Name</form:label>
<form:input placeholder="Enter country Name" path="countryName"
class="form-control" name="countryName"
value="${countryMaster.countryName}" required="true"
data-error="country Name cannot be empty" />
<form:errors path="countryName" cssClass="text-red" />
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="box-footer">
<form:button type="button" onclick="window.location.reload()" class="btn pull-left btn-primary">Clear</form:button>
<div class="pull-right">
<button onclick="submitTheForm()" class="btn btn-primary">Add Country</button>
Cancel
</div>
</div>
</form:form>
AJAX
function submitTheForm(){
var value = $("#addCountryForm").serialize();
$.ajax({
type : "post",
url : 'addSaveCountry.html',
dataType: "json"
data : {
countryMaster : value
},
success: function(result){
console.log(result);
if(resule.localeCompare("Some exception occured, try again.") == 0) {
/**
* Give a div where you display this message
**/
} else if(result.localeCompare("New Country Inserted")) {
var alert = "<div class=\"alert alert-success alert-dismissible\" role=\"alert\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">x</span>";
alert += "</button>";
alert += "<strong>"+result+"!</strong>";
alert += "</div>";
var informationDiv = alert + "<br>";
document.getElementById("informationDiv").innerHTML = informationDiv;
} else {
var alert = "<div class=\"alert alert-success alert-dismissible\" role=\"alert\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">x</span>";
alert += "</button>";
alert += "<strong>"+result+"!</strong>";
alert += "</div>";
var informationDiv = alert + "<br>";
document.getElementById("informationDiv").innerHTML = informationDiv;
}
}
});}
Controller Code
#RequestMapping(value="/addSaveCountry", method = RequestMethod.POST)
public #ResponseBody String addCountryPost(#Validated #ModelAttribute("countryMaster") Country country, BindingResult result){
try {
if (result.hasErrors()) {
Gson gson = new Gson();
String json = gson.toJson("Some exception occured, try again.");
return json;
}
int companyId = 1;
country.setCompanyId(companyId);
String createdBy, lastUpdatedBy;
createdBy = "IN129";
lastUpdatedBy = "IN129";
country.setCreatedBy(createdBy);
country.setLastUpdatedBy(lastUpdatedBy);
java.sql.Timestamp curTime = new java.sql.Timestamp(new java.util.Date().getTime());
country.setCreatedDate(curTime);
country.setLastUpdatedDate(curTime);
boolean status = countryService.addorupdateCountry(country);
if (status == true) {
Gson gson = new Gson();
String json = gson.toJson("New Country Inserted");
return json;
} else {
Gson gson = new Gson();
String json = gson.toJson("New Country Insertion Failed, Try Again Later");
return json;
}
}}
When I run it and try to insert, I am getting
"HTTP Status 405 - Request method 'POST' not supported"
message - Request method POST not supported
description - The specified HTTP method is not allowed for the requested resource.
Thanks in advance.

Change your URL from html suffix :
url : 'addSaveCountry.html',
To Path of RequestMapping
url : '/addSaveCountry',
also change to type: "POST" (uppercase)

Related

ajax post failed but controller & db data ok

im posting data to controller with partailview the controller receive valid data & store it in my DB but:
im getting ajax failed Msg.
im not getting a TempData displayed as expected ( i have one for results OK and else for error).
Im not sure where to put my finger on .
Index View
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
function SubmitREgNews() {
var data = {
userName: $("#name").val(),
UserMail: $("#email").val(),
TermsOk: $("#bOk").val(),
};
$.ajax({
type: 'POST',
url: "/NewsLetter/Create",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: data,
success: function(result) {
alert('Successfully received Data ');
console.log(result);
},
error: function() {
alert('Failed to receive the Data');
console.log(JSON.stringify(error));
console.log('Failed ');
}
});
}
Partial view
#if (#TempData["ErrorMes"] != null)
{
#TempData["ErrorMes"]
}
#if (#TempData["regOk"] == null)
{
<div class="row">
<div class="col-md-4">
<form id="studenteForm" novalidate class="needs-validation">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="userName" class="control-label"></label>
<input asp-for="userName" class="form-control" id="name" required />
</div>
<div class="form-group">
<label asp-for="UserMail" class="control-label"></label>
<input asp-for="UserMail" type="email" class="form-control" id="email" /> </div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" id="bOk" asp-for="TermsOk" /> #Html.DisplayNameFor(model => model.TermsOk)
</label>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" onclick="SubmitREgNews();">Add </button>
</div>
</form>
</div>
</div>
</div>
}
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
controller
public IActionResult _RegNews()
{
return PartialView();
}
[HttpPost]
public async Task<IActionResult> Create([Bind("JoinId,userName,UserMail,TermsOk")] JoinNews joinNews )
{
var IsNewUser = await _context.joinNewsL.FirstOrDefaultAsync(a =>
a.UserMail.ToUpper() == (joinNews.UserMail.ToUpper()));
if ( ModelState.IsValid && IsNewUser==null)
{
joinNews.JoinId = Guid.NewGuid();
joinNews.JoinDate = DateTime.Now;
_context.Add(joinNews);
await _context.SaveChangesAsync();
TempData["regOk"] = "You are register";
return View("home/index");
}
else
{
TempData["ErrorMes"] = "You are allready register";
}
return PartialView("_RegNews", joinNews);
}
The reason you are getting ajax failed Msg may be that you are returning the wrong path "home/index". Paths in one controller that call a page in another controller should use "../home/index".
Also, Ajax doesn't change page elements. If you want to redirect to another page you can use Url.Action.
Like this:
Controller:
[HttpPost]
public async Task<IActionResult> Create([Bind("JoinId,userName,UserMail,TermsOk")] JoinNews joinNews)
{
var IsNewUser = await _context.joinNewsL.FirstOrDefaultAsync(a =>
a.UserMail.ToUpper() == (joinNews.UserMail.ToUpper()));
if (ModelState.IsValid && IsNewUser == null)
{
joinNews.JoinId = Guid.NewGuid();
joinNews.JoinDate = DateTime.Now;
_context.Add(joinNews);
await _context.SaveChangesAsync();
TempData["regOk"] = "You are register";
return Json(new { redirectUrlOne = Url.Action("Index", "Home")});
}
else
{
TempData["ErrorMes"] = "You are allready register";
return Json(new { redirectUrlTwo = Url.Action("_RegNews", "NewsLetter") });
}
}
And your ajax:
$.ajax({
type: 'POST',
url: "/NewsLetter/Create",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: data,
success: function (result) {
alert('Successfully received Data ');
if (result.redirectUrlOne !== undefined) {
window.location.replace(result.redirectUrlOne);
} else {
window.location.replace(result.redirectUrlTwo);
}
console.log(result);
},
error: function (error) {
alert('Failed to receive the Data');
console.log(JSON.stringify(error));
console.log('Failed ');
}
});
If you don't want to use Url.Action, you can also do not use Ajax, using the Form Tag Helper to submit data is the same. You can check the details in this official document.

Updating a list with ajax and razor

I have a page in asp.net core razor, which is updating the database. I use ajax to go to the controller, the world is done, but I am not able to update the list that the ajax method returns.
This is my ajax method:
$.ajax(
{
url: "/Uploader/Update",
type: 'post',
data: {
Id: valor
},
success: function (data) {
$("#LaudosDocumentos").html(data);
}
})
Here is my Controller:
public async Task<IActionResult> Update(int Id)
{
ApplicationUser user = await _userManager.GetUserAsync(User);
if (!ModelState.IsValid)
{
return NotFound();
}
Laudos = _context.Laudos.Find(Id);
Laudos.Excluido = true;
Laudos.AlteracaoUsuId = user.Id;
_context.Attach(Laudos).State = EntityState.Modified;
await _context.SaveChangesAsync();
Id = Laudos.PessoaId;
LaudosDocumentos = await _context.Laudos.Where(m => m.PessoaId == Id && m.Excluido == false).ToListAsync();
return Json( new { LaudosDocumentos });
}
This is my page cshtml:
<div class="col-sm">
#if (Model.LaudosDocumentos.Count > 0)
{
<label class="control-label" style="margin-left:10px">
Arquivo(s) encontrado(s)
</label>
}
else
{
<label class="control-label" style="margin-left:10px">
Nenhum arquivo foi enviado para analise.
</label>
}
<div class="btn btn-default btn-file">
#foreach (var item in Model.LaudosDocumentos)
{
var ponto = item.Caminho.IndexOf(".");
var extensao = item.Caminho.Substring(ponto + 1);
if (extensao == "png" || extensao == "jpg" || extensao == "gif" || extensao == "jpeg")
{
<a class="example-image-link" href="/uploads/#Html.DisplayFor(modelItem => item.PessoaId)/#Html.DisplayFor(modelItem => item.Caminho)" data-lightbox="example-set" data-title="">
<img src="/uploads/#Html.DisplayFor(modelItem => item.PessoaId)/#Html.DisplayFor(modelItem => item.Caminho)" class="img-thumbnail" alt="Laudos" style="width:200px; height:200px;" />
</a>
<span style="font-size:23px; margin-left:10px;"> <i class="far fa-trash-alt" onclick="ExcluirArquivo(#Html.DisplayFor(modelItem => item.Id));"></i></span>
<span> <i class="far fa-trash-alt" onclick="ExcluirArquivo(#Html.DisplayFor(modelItem => item.Id));"></i></span>
}
}
</div>
</div>
I just need to update the list Model.LaudosDocumentos
but without having to pass the Id of a div.
I've tried to pass the item value in ajax but it also didn't work.
Json( new { LaudosDocumentos }) will return Json data , you should create your html markup and associated with Json value using Javascript , here is code sample .
If you don't want to create html in javscript manually , you can put the whole <div> to partial view , and use ajax to call server side function to query/load the partial view with passed model/value , and at last in success function of Ajax directly load the html using .html(result); . Here is coed sample .

Load dynamic image from external url in thymleaf img tag[SringBoot]

I have a Dynamic external url that i am setting in model at controller side and trying to access in html using thymleaf tag
Here is the code:
Controller:
#RequestMapping(value = "/{id:.+}", method = RequestMethod.GET)
public String searchUser(#PathVariable("id") String data, Model model) {
/*
* if (!data.startsWith("#")) { data = "#" + data; }
*/
List<User> list = userService.searchUserUsingText(data);
if (list.isEmpty()) {
System.out.println("error");
return "404";
} else {
User user = list.get(0);
if (null != user.getName())
model.addAttribute("name", user.getName());
if (null != user.getProfession())
model.addAttribute("profession", user.getProfession());
if (null != user.getPhotoUrl()) {
System.out.println("inside image" + user.getPhotoUrl());
model.addAttribute("image" + user.getPhotoUrl());
}
return "profile";
}
}
PhotoUrl will be a external url like:
https://firebasestorage.googleapis.com/v0/b/mysocialhandle-ecfc0.appspot.com/o/images%2FFtX4VVciacM1jKdrP2NfInSyWMf1%2FFtX4VVciacM1jKdrP2NfInSyWMf1.jpg?alt=media&token=10e06c9b-044e-4e15-ab74-a55429bcb22b
Thymleaf/Html side:
<div class="container">
<div class="owner">
<div class="avatar">
<img th:src="#{${image}}" alt="Circle Image"
class="img-circle img-no-padding img-responsive">
</div>
<div class="name">
<h4 class="title" th:text="${name}">
<br />
</h4>
<h6 class="description" th:text="${profession}"></h6>
</div>
</div>
name and profession are resolved perfectly but at img Tag i am getting null.
Guys please help in this...
You have
model.addAttribute("image" + user.getPhotoUrl());
I think you meant to have
model.addAttribute("image", user.getPhotoUrl());

Spring MVC and bootstrap modal form : how to create server-side validation for it?

I'm newbie at spring and front-end at all.
I have (not mine) an old front-end code to show modal form over some page :
modal form is:
<div id="myModalForm" class="modal inmodal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog ">
<div class="modal-content animated fadeIn">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span
aria-hidden="true">×</span><span class="sr-only"></span></button>
<h4 class="modal-title"><spring:message code="entity.modal.title"/></h4>
</div>
<div id="modalContent" class="modal-body">
<form id="createForm" name="createForm" class="" action="/entity/create"
method="post" enctype="multipart/form-data">
...
</form>
</div>
</div>
</div>
</div>
form is shown from java scripts. Button that invokes form is:
<script>
$(document).ready(function () {
$('#tbl').DataTable({
responsive: true,
dom: 'l<"toolbar">frtip',
initComplete: function () {
$("div.toolbar")
.html('<button id="new_entity_btn" type="button" class = "btn btn-white" onclick="openCreateWindow()" ><spring:message
code="entity.table.create.btn"/> </button>');
}
});
/*activate tooltips*/
$(function () {
$('[data-toggle="popover"]').popover();
});
});
</script>
and onclick for button is:
<script>
function openCreateWindow() {
$('#myModalForm').modal('show');
}
</script>
Now as you can see #myModalForm is not a Spring view form as it doesn't generate even get-request to be shown. It just appears over existing page in modal mode. Now the question is how to create server-side validation for it? I've tried next:
1) refactor it to spring mvc form i.e. via
<form:form ... />
tag with attribute
ModelAttribute='MyFormAttribute'. But i have no idea how to create back-end object for MyFormAttribute as appearance of form doesn't generate get-request. And idea was to have on post method of controller something like:
#RequestMapping(value = {"/entity/create"}, method = RequestMethod.POST)
String createNewEntity(
#ModelAttribute("MyFormAttribute") MyEntity entity,
BindingResult bindingResult,
Model model)
2) Trying to change post method of controller so that it might return error. But there is no way to create bindingResult parameter in case if form is not mvc one
3) Trying to validate via jQuery.validate i.e. smth. like :
<script>
/*form validation*/
$().ready(function () {
$("#createForm").validate({
rules: {
Field1: {
remote: function () {
var r = {
url: '/validateEntityField1',
type: "POST"
};
return r;
}
},
Field2: {
remote: function () {
var r = {
url: '/validateEntityField2',
type: "POST"
};
return r;
}
}
...
},
errorElement: "em",
highlight: function (element, errorClass, validClass) {
$(element).fadeOut(function () {
$(element).fadeIn();
});
$(element).addClass(errorClass).removeClass(validClass)
},
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass)
}
})
;
});
</script>
But it looks rather ugly as i should validate every field separately on its own end point and. Besides form has file input so i should send it twice or smth.
So, how could i achieve next issue:
leave modal form over existing page
validate it on server side. It would be nice to make validation against whole entity.
Answering on my commented question. Not the exact code you are looking but will give you an idea. Though it depends on individual choice, in controller you can use ValidationUtils as shown below. Here you can map your error messages and json response which later on you want on your front-end:
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public #ResponseBody JsonResponse addUser(#ModelAttribute("user") User user, BindingResult result, Errors errors, Model model) {
JsonResponse response = new JsonResponse();
ValidationUtils.rejectIfEmptyOrWhitespace(result, "firstname", "Firstname is required. It can not be empty.");
if (user.getFirstname().length() < 4 || user.getFirstname().length() > 32) {
errors.rejectValue("firstname", "Firstname must be between 4 and 32 characters.");
}
ValidationUtils.rejectIfEmptyOrWhitespace(result, "lastname", "Lastname is required. It can not be empty.");
if (user.getLastname().length() < 4 || user.getLastname().length() > 32) {
errors.rejectValue("lastname", "Lastname must be between 4 and 32 characters.");
}
if (!result.hasErrors()) {
userList.add(user);
response.setStatus("SUCCESS");
response.setResult(userList);
} else {
response.setStatus("FAIL");
response.setResult(result.getAllErrors());
}
return response;
}
And I picked the sample for Bootstrap Modal from here:
https://www.w3schools.com/bootstrap4/bootstrap_modal.asp
Somewhere in your html:
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<label class="col-form-label" for="username">Enter your First Name</label>
<i class="fas fa-users"></i>
<input type="text" id="firstname" class="form-control">
</div>
....
....
</div>
Put up (similar to this) in your ajax:
if (response.status == "SUCCESS") {
userInfo = "<ol>";
for (i = 0; i < response.result.length; i++) {
userInfo += "<br><li><b>Firstname</b> : "
+ response.result[i].firstname
+ response.result[i].lastname;
}
And
errorInfo = "";
for (i = 0; i < response.result.length; i++) {
errorInfo += "<br>" + (i + 1) + ". "
+ response.result[i].code;
}
$('#error').html(
"<b>Errors found during validation : </b>"
+ errorInfo);
I created a small piece of code for this. You can take a look here on GitHub.

Umbraco BlogComment Create Ajax

Hello im trying to post my blog comments the function works. but the whole site refreshes inside the div, i tried playing around with the partialview in the controller but im not sure what to do can anybody here point me in the right directtion, i want div to refresh with ajax request not the whole site intro the div.
<!-- Blog Comments -->
<!-- Comments Form -->
<div class="well">
<h4>Leave a Comment:</h4>
#if (Members.GetCurrentLoginStatus().IsLoggedIn)
{
using (Html.BeginUmbracoForm("CreateComment", "CommentSurface", FormMethod.Post, new { #id = "comment-form" }))
{
// use this where every display profile image is needed
var user = User.Identity.Name;
var imgUrl = Url.Content("~/media/profileimage/" + user.Replace(".", "") + ".png");
<input name="CommentOwner" type="text" value="#Members.GetCurrentMember().Name" class="form-control hidden" readonly="readonly" />
<input name="ownerid" type="text" value="#Members.GetCurrentMember().Id" class="form-control hidden" readonly="readonly" />
<div class="form-group">
<textarea name="Message" rows="3" placeholder="Type your message here" class="form-control"></textarea>
</div>
<input name="profileimage" type="text" value="#imgUrl" class="hidden" readonly="readonly" />
<button type="submit" class="btn btn-primary">Submit</button>
}
}
else
{
<p> You are not logged in Register here</p>
}
</div>
<hr>
<!-- Posted Comments -->
<div class="blog-comments">
#Html.Partial("_BlogComments")
</div>
<!-- Comment -->
#section scripts {
<script>
$(function () {
// Find the form with id='well-form'
$('#comment-form').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (data) {
$(".blog-comments").html(data);
},
error: function (result) {
alert('Comment was not successful!');
}
});
// return false to cancel the form post
// since javascript will perform it with ajax
return false;
});
});
</script>
}
</div>
SurfaceController:
public class CommentSurfaceController : SurfaceController
{
[HttpPost, ValidateInput(false)]
public ActionResult CreateComment(CommentViewModel model)
//public PartialViewResult CreateComment(CommentViewModel model)
{
if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}
var contentService = Services.ContentService;
var newContent = contentService.CreateContent(DateTime.Now.ToShortDateString() + " " + model.CommentOwner, UmbracoContext.PageId.Value, "BlogComment");
newContent.SetValue("CommentOwner", model.CommentOwner);
newContent.SetValue("Message", model.Message);
newContent.SetValue("profileimage", model.profileimage);
newContent.SetValue("ownerid", model.ownerid);
//Change .Save if u want to allow the content before publish
contentService.SaveAndPublishWithStatus(newContent);
return RedirectToCurrentUmbracoPage();
//return PartialView("BlogComments", model);
}
public ActionResult DeleteComment(int commentid)
{
var service = ApplicationContext.Current.Services.ContentService;
var content = service.GetById(commentid);
service.Delete(content);
return RedirectToCurrentUmbracoPage();
}
}
Partial View:
#foreach (var item in Model.Content.Children().OrderByDescending(m => m.CreateDate))
{
<div class="media">
<a class="pull-left" href="#">
<img class="media-object" width="64" src="#item.GetPropertyValue("profileimage")" alt="profile image">
</a>
<div class="media-body">
<h4 class="media-heading">
#item.GetPropertyValue("CommentOwner")
<small>#item.CreateDate</small>
</h4>
#item.GetPropertyValue("Message")
</div>
#item.Id
</div>
if (Members.GetCurrentLoginStatus().IsLoggedIn)
{
if (#Members.GetCurrentMember().Id.ToString() == item.GetPropertyValue("ownerid").ToString())
{
#Html.ActionLink("Delete", "DeleteComment", "CommentSurface", new { commentid = item.Id }, null)
}
else
{
#*<p> not ur comment</p>*#
}
}
else
{
//blank cant delete comment if not logged in
}
}
The problem is that UmbracoSurfaceController is loosing his context if you are not rendering the complete page.
If you work with ajax, you should not render out html and post this back. Only POST the data and update your layout in javascript when you get a 200 (ok) back from the server.
To do so, use the UmbracoApiController. This is a WebApi controller allowing you to send back json (or xml) serialized data.
More information about the UmbracoApiController can be found in the documentation.

Resources