Value is not printed on JSP page - spring-mvc

model.addAttribute("error",ErrorMessages.USERLOGINERROR);
is not working while using redirect
return "redirect:/userlogin";
I have google it but not found approciate answer
if(name.equals("false")){
System.out.println(ErrorMessages.USERLOGINERROR);
model.addAttribute("error",ErrorMessages.USERLOGINERROR);
return "redirect:/getuserloginpage";
}
JSP:
<form:form action="userlogin" method="post" commandname="login">
<div align="center" style="color: red">${error}</div>
<div align="center" style="color: red">${thanks}</div>
...
expected result should be :
Please check your email or password. actual results : printed nothing.
(no error or exception found)

Do one thing, you are using
return "redirect:/userlogin";
it means you have
#RequestMapping(value="/userlogin", method=GET)
public String yourMethod(Model model)
{
your code.....
return some_page_name;// from tiles.xml or directly as per you configuration
}
now use the same return
if(name.equals("false")){
System.out.println(ErrorMessages.USERLOGINERROR);
model.addAttribute("error",ErrorMessages.USERLOGINERROR);
//return "redirect:/getuserloginpage";
return some_page_name; // simple and easy but take care of functionality
}

Normal model attributes will not work with redirect.
Use redirect attributes instead like below.
#RequestMapping(value="/someURL", method=GET)
public String yourMethod(RedirectAttributes redirectAttributes)
{
...
redirectAttributes.addAttribute("rd", "rdValue");
redirectAttributes.addFlashAttribute("fa", faValue);
return "redirect:/someOtherURL";
}

Related

Concrete5 validation not working on a single page

I am trying to validate a form on a single page. Below is what I've tried but $validation->test() doesn't seem to be working. It's supposed to redirect to another page upon validating the first_name field. I get stuck at this url: http://localhost/mysite/index.php/buy/process/. I am using 5.6.x. Not sure what I am doing wrong.
public function process() {
$validation = Loader::helper('validation/form');
$validation->setData($this->post());
$validation->addRequired($this->post('first_name'), 'First Name must not be empty');
if ($validation->test()) {
....
....
$this->redirect('/buy/step2');
} else {
$errorArray = $validation->getError()->getList();
$this->set('errorArray', $errorArray);
}
}
This function is called from the view:
<form enctype="multipart/form-data" id="buy" class="buy-form" method="post" action="<?php echo $this->action('process')?>">.....</form>
I had to replace
$validation->addRequired($this->post('first_name'), 'First Name must not be empty');
with
$validation->addRequired('first_name', 'First Name must not be empty');
That did it.

Send a post parameter with path

I have a list of demands, that I can remove some, so I have created a path for every demand like that:
<a href="{{ path('etudiant_suprimer_demande',{'id':demande.id} )}}
And I have a controller like that:
class EdudiantController extends Controller
{ //codes
public function suprimerdemandeAction($id){
// echo $id;
$em = $this->getDoctrine()
->getEntityManager();
$demande = $em->getRepository('AcmeEstmSiteBundle:Demande')
->find($id);
if ($demande == null) {
throw $this->createNotFoundException('Demande[id='.$id.']inexistant');
}
if ($this->get('request')->getMethod() == 'POST') {
$this->get('session')->getFlashBag()->add('info', 'Demande bien supprimée');
return $this->redirect( $this->generateUrl('acme_estm_site_espace_etudiant'));
}
//return $this->render('SdzBlogBundle:Blog:supprimer.html.twig',array('demande' => $demande));
return new Response();
}
And the routing is:
etudiant_suprimer_demande:
path: /profile/espace/suprimerdemande/{id}
defaults: { _controller: AcmeEstmSiteBundle:Edudiant:suprimerdemande }
methods: POST
What I want is do not show the id of demands in the URL, that means I want this action with a post method but I have this error:
No route found for "GET /profile/espace/suprimerdemande/3": Method Not Allowed (Allow: POST)
TL;DR
<form action="{{ path('etudiant_suprimer_demande',{'id': demande.id} )}}" method="post">
<button type="submit">Delete</button>
</form>
Explanation
The code you have now only generates an <a> link, which when a user clicks it, his user agent sends a GET request to the server, thus the error you get.
In order to create a POST request, you need a <form>.
To answer your question regarding showing ID in the generated URL, take a look at this answer. You'll have to change your controller and routing.

Thymeleaf SpringMVC page footer doesn't find Controller

I have a spring boot project that uses SpringMVC and Thymeleaf. I have a footer defined in a layout.html that is included on every page. Is there anyway to include a a call on that footer that shows "status" for each page. This way when you navigate the site, the page footer will always show desired information?
I have a REST Controller that puts a Status object:
#Controller
public class StatusController {
#RequestMapping(value = "/status", method = RequestMethod.GET)
public String get(Model model) {
Status status = new Stauts;
LocalDate lastUpdate = statusRepository.findByLastUpdate();
...
// do some work to update the status object
model.addAttribute( STATUS, status );
return "status";
}
I have a in my footer.html this defined:
<div th:fragment="foot">
<div id="footer">
<div class="container">
<p class="muted credit">
<form action="refreshData" th:action="#{/status}" method="get"></form>
Last update status: <span th:text="${status.status}" class="text-info"></span>
</p>
</div>
</div>
</div>
And then each page includes the footer as such:
...
<div th:include="layout :: foot"></div>
</body>
I put a breakpoint in my controller and its not called, and I always get this exception on page load:
org.springframework.expression.spel.SpelEvaluationException:
EL1007E:(pos 0): Property or field 'status' cannot be found on null
I wonder if the Controller is never called because I have to use something like jQuery to make Ajax calls, or because I have this in my layout.html and that include doesn't make calls (which seems unlikely)?
In Spring MVC you only have one controller per page/call. You cannot call several controllers in one shot. I believe this is your issue.
You have multiple possibilites:
Either you have to incorporate this status variable in each controller yourself.
create a ControllerAdvice that prepares the model attribute status and is applied to each controller (default)
use a service call in your footer to fetch the status like: th:text="${#statusService.status}"
I for myself like the service approach for these kind of global available information.
CURRENT:
<span th:text="${status.status}" class="text-info">
CHANGE TO
<span th:text="${status}" class="text-info">
this will display null
in the controller you have set Status status = null; and set it in the model map to attribute status".
So ${status} is evaluated as null (this is nothing but model.get("status")). ${status.status} will be null.status .
Resulting in
'status' cannot be found on null

src vs srctarget vs srcwait

I continue to work on a project that I do not fully understand yet. I encountered the following line of code:
<iframe id="AddDialog" style ="overflow: hidden; width:1150px; height:450px;" class="Dialogframe" scrolling="no" srcwait=#Html.Raw("'" + Url.Action("Index", "FieldChooser") + "'") srctarget=#Html.Raw("\"" + Url.Action("Index", "FieldChooser", new { ColumnFormat = false, resultmodel = Guid.Empty, datatype = "", multiselect=false }) + "\"") src=#Html.Raw("\"" + Url.Action("Loading", "FieldChooser") + "\"")></iframe>
Visual Studio tells me that srcwait and srctarget are not valid HTML5-elements, but it seems to work. The Loading View is shown for a few seconds and then the Index() method is executed (the one called in srctarget).
I am also not able to find anything on the internet about the attributes srctarget and srcwait. So what are the differences between src, srctarget and srcwait? Do they even exist or is that some invention of the person that worked on it before me?
I have a function in the FieldChooserController
[HttpPost]
public ActionResult Index(string id)
{
...
}
I want this to be called when I click on the OK button. I assumed that the srcwait part is meant for that because the call looks like that, but the function is never called.
Please bear with me and tell me if you need to see more code, at this point I have no idea what is important.
buttons: {
OK: function() {
//Save selected Value
$( this ).dialog( "close" );
if (GlobalName !=''){
addwhere(GlobalName,opts.sourceel,GlobalDefVal,GlobalDataType,GlobalValue);
}
$('#AddDialog').attr('src', $('#AddDialog').attr('srcwait'));
},
Cancel: function() {
$( this ).dialog( "close" );
$('#AddDialog').attr('src', $('#AddDialog').attr('srcwait'));
}
}
There most probably is a piece of JavaScript running, which sets the src to srcwait when an operation is performed where the user will be waiting for a wile, for example to show a loading screen.
As for your code, if you have a HttpPost annotated Index() method you wish to call upon a button click, you must create a form and let it post there:
#using (Html.BeginForm("Index", "FieldChooser", FormMethod.Post)
{
<input value="OK" type="submit" />
}

Returning data to a partial view

I have a blog that has a sidebar with a partial view in it that enables users to sign up for my e-mail newsfeed. What I'm trying to do is returning the user to the page they came from after posting some data, and displaying any validation or return messages in the form's partial view.
The problem is that my partial view opens in a new window (without the lay-out). How can I fix this so it returns to my blog, with the return data in de sidebar?
This is my view:
#using Blog.Models.Entities
#model Subscriber
<header>
<h2>Subscribe</h2>
</header>
<p>Subscribe to my e-mail newsfeed.</p>
#using (Html.BeginForm("Form", "Subscription"))
{
<div class="editor-label">#Html.LabelFor(subscriber => subscriber.Email)</div>
<div class="editor-field ">#Html.EditorFor(subscriber => subscriber.Email)</div>
#Html.ValidationMessageFor(subscriber => subscriber.Email)
<input type="submit" value="Subscribe" />
<p>#ViewBag.Result</p>
}
And the relevant pieces of controller that are processing the data:
public ActionResult Form()
{
return PartialView("_Form");
}
[HttpPost]
public ActionResult Form(Subscriber subscriber)
{
if (ModelState.IsValid)
{
Subscriber foundSubscriber = _repository.Subscribers.Where(s => s.Email.Equals(subscriber.Email)).FirstOrDefault();
if (foundSubscriber != null)
{
ModelState.AddModelError("Email", "This e-mail address has already been added.");
return PartialView("_Form", subscriber);
}
_repository.SaveSubscriber(subscriber);
ViewBag.Result = "Succesfully subscribed to the newsletter.";
return PartialView("_Form");
}
ModelState.AddModelError("Email", "Please provide a valid e-mail address.");
return PartialView("_Form", subscriber);
}
When submitting a form, the browser sends an HTTP Post request to the server. The browser then displays the Response's payload. Your post Controller Action is returning a PartialView, which the browser is happily rendering (even though it doesn't have the html, head, or body tags necessary to make it truly valid HTML).
It sounds like you want the browser to keep most of your page loaded and rendered, post the form, then take the resulting HTML and only replace a portion of the loaded page. Simply put, the browser isn't smart enough to do that.
What you probably want to do is something like this:
User fills in some form data and clicks save/submit/go/whatever.
However, you don't want the browser to submit the form, because it won't preserve most of the current page the way you want.
Instead, you want the "submit" button to call some local javascript.
That local JS should bundle up the user-entered form data, craft a POST with that data as the payload, and submit the POST using Ajax. This will keep the current page loaded, while the ajax request hits your Controller Action
You controller action stays the way it is, and returns a partial view.
Your JS function that launched the Ajax call must also define a "success" function which will get called when the operation completes.
Within that success function, your javascript will grab the HTML from the response, and use it to replace the area of the page that held the original form.
I highly recommend jQuery - it will make it MUCH easier to craft the Ajax request, handle the success callback, and replace just a section of the currently-loaded page with the result. My understanding is that MS's 'unobtrubsive javascript' may also help implement this, however I don't have any direct experience with it.
Obviously, all of this will only work if the browser has javascript enabled.
I finally found the solution to the problem. I implemented it with AJAX and ended up with the following code:
_Index.cshtml
<header>
<h2>Subscribe</h2>
</header>
<p>Subscribe to my e-mail newsfeed.</p>
<div id="subscription-form">
#{Html.RenderPartial("_Form");}
</div>
_Form.cshtml
#using Blog.Models.Entities
#model Subscriber
#{
AjaxOptions ajaxOptions = new AjaxOptions
{
LoadingElementId = "loading",
LoadingElementDuration = 2000,
HttpMethod = "Post",
UpdateTargetId = "subscription-form"
};
}
<div id="loading" style="display: none;">
<p>Processing request...</p>
</div>
#using (Ajax.BeginForm("Index", "Subscription", ajaxOptions))
{
<div class="editor-label">#Html.LabelFor(subscriber => subscriber.Email)</div>
<div class="editor-field ">#Html.EditorFor(subscriber => subscriber.Email)</div>
#Html.ValidationMessageFor(subscriber => subscriber.Email)
<input type="submit" value="Subscribe" />
}
_Succes.cshtml
#using Blog.Models.Entities
#model Subscriber
<p id="subscription-result">#ViewBag.Result</p>
And the following controller action methods:
public ActionResult Index()
{
return PartialView("_Index");
}
[HttpPost]
public PartialViewResult Index(Subscriber subscriber)
{
if (ModelState.IsValid)
{
Subscriber foundSubscriber = _repository.Subscribers.Where(s => s.Email.Equals(subscriber.Email)).FirstOrDefault();
if (foundSubscriber != null)
{
ModelState.AddModelError("Email", "This e-mail address has already been added.");
return PartialView("_Form", subscriber);
}
_repository.SaveSubscriber(subscriber);
ViewBag.Result = "Succesfully subscribed to the newsletter.";
return PartialView("_Succes", subscriber);
}
ModelState.AddModelError("Email", "Please provide a valid e-mail address.");
return PartialView("_Form", subscriber);
}
I hope this will help anyone trying to achieve the same in the future. BTW, I found the solution on this blog: http://xhalent.wordpress.com/2011/02/05/using-unobtrusive-ajax-forms-in-asp-net-mvc3/.

Resources