MVC3 pass exception from controller to view - asp.net-mvc-3

want to print the exception on cshtml page, but unbale to get where to use this
#Html.ValidationSummary()
<form method="post" action="AddUser">
</form>

You should add error message in action like this.
ModelState.AddModelError(string.Empty, "error message.");
and use #Html.ValidationSummary() in view.

Related

How to add an element id to the url of the Thymeleaf template in the controller in Spring

I have a Spring Application and Server Side Rendering with Thymeleaf as Templating language.
A button sends a get or post request to the controller in Spring, which puts some message to the view, which is rendered into the HTML file and send back to the client. The message should be optional. Thats why the template must also be able to be called without the message.
Next i want the client browser to scroll down to the part of the page where this message is rendered into, which is normally very easy. You would just have to append the id of the element to the url like following example.
https://stackoverflow.com/#footer
In this example the browser scrolls down to the footer of the page.
Below is what i tried. Unfortunately it doesnt't work like that. Spring/Thymeleaf tries to find a index#messagebox template which can't be found. Hence a Whitelabel Error Page error is thrown/shown.
Page.html
<section>
<h2>Form to send request</h2>
<form action="showmessage" method="get">
<input type="submit" value="Click for message">
</form>
</section>
Controller.java
#GetMapping("showmessage")
public ModelAndView showMessage(){
return new ModelAndView("index#messagebox",Map.of("optionalmessage","Some message that is optioal"));
}
src/main/resources/templates/index.html
<body>
<h1>Index Page</h1>
<div id="messagebox" th:fragment="message" th:with="optionalmessage=${optionalmessage}">
<p th:if="${optionalmessage!=null}">[[${optionalmessage}]]</p>
</div>
</body>
The problem can be solved with Flashmessages and Redirects. The html basically keeps the same. If the message attribute is set, you render it.
src/main/resources/templates/index.html
<div th:if="${msg}">
<div class="message" >
<p>[[${msg}]]</p>
</div>
</div>
The most important changes had to be made in the controller. First a parameter of type RedirectAttributes is added to the Controller that handles the request.
If wanted the message is added with the RedirectAttributes.addFlashAttribute function as shown below. Finally a redirect is returned, which contains the needed tag. A second controller is also needed that handles the Get Request of the Redirect with a Model as input parameter and returns the needed Template. The #tag is simply passed throuhg to the client browser.
Controller.java
#GetMapping("showMessage")
public String postNotification(RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("optinalMessage", "Hello I am an optional message");
return "redirect:/index#footer";
}
#GetMapping("index")
public String getIndex(Model model) {
return "index";
}
You add id in URL by using ?id=value.
And in controller #RequestMapping("/path/{id}")
to access that variable #PathVariable

Form validation in Spring

I want to show errors for all the form, not single field. So I did this:
public void validate(Object target, Errors errors) {
AddUserForm addUserForm = (AddUserForm) target;
if (addUserForm.getPassword().length() == 0) {
errors.reject("Message error");
}
}
Now I'm using reject method instead of rejectValue, because I don't need to set error message to one field.
And this is my jsp:
<form:form method="POST" commandName="addUserForm"
class="form-horizontal" style="width: 510px;">
<form:errors ??? />
...
Which attribute should I use now? I was trying this:
<form:errors commandName="addUserForm"/>
But doesn't help.
If you are rejecting by using a fieldName in form object as:
errors.rejectValue("fieldName", "errorMessage");
This you can display in view as:
<form:errors path="fieldName"/>
If you are rejecting without specifying the fieldname in form object i.e., raising the error on whole form object then you can set these errors as:
errors.reject("Message error");
This you can display in view without any attributes as:
<form:errors/>

MVC3: unable to return Login validation error messages to Index.cshtml with Login PartialView

I am new to MVC (with 2 years in WebForms). I am trying to implement Login using PartialView in my Index.cshtml as follow:
#Html.Action("LogOnPartial")
If the username or password is incorrect, the called method will reach this line as expected:
ModelState.AddModelError("", "The user name or password provided is incorrect.");
Because it is a partial view, I pass the model back to the Index.cshtml as follow in order to show the 'incorrect' entries:
// If we got this far, something failed, redisplay form
return View("Index", model);
Then Index.cshtml will then call #Html.Action("LogOnPartial"), which in turn trigger this:
[HttpPost]
public ActionResult LogOnPartial(LogOnModel model)
{
return PartialView(model);
}
After rendering, the 'incorrect' entries will remain in the textbox as expected, but the above error message "The user name or password provided is incorrect." is not displayed. I guess the error messages are not passed in the above method.
How can I show the error message when returning from the partial view?
Thanks.
Thanks Marks, your suggestion is very helpful. Originally I already included #Html.ValidationSummary() in the end of my LogOnPartial.cshtml but somehow the error message didn't show up in the Index.cshtml. Now I moved the #Html.ValidationSummary() to Index.cshtml as follows:
#Html.Action("LogOnPartial")
#Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
and now it works ok and I can see the login error message.
However, now I have another problem. There are two partial views in my Index.cshtml. One is for the LogOnPartial.cshtml and the other is for SignUpPartial.cshtml (you may want to take a look at www.iguardpayroll.com, which is written in WebForms, and you will see there are two boxes in the left column: one is for Login and the other is for Sign Up).
In additional to adding the #Html.ValidationSummary() right underneath the #Html.Action("LogOnPartial"), I also need to add it under the #Html.Action("SignUpPartial") in order to show the error message caused by the signup process (e.g. email already exists!). However, if I do that the same LogOn error message will appear twice under both the LogOn part and the SignUp part.
<div>
#Html.Action("LogOnPartial")
#Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
</div>
<div>
#Html.Action("SignUpPartial")
#Html.ValidationSummary(true, "Sign Up was unsuccessful. Please correct the errors and try again.")
</div>
How can I tell the first #Html.ValidationSummary() only shows the error message related to LogOnPartial, and the 2nd #Html.ValidationSummary() only shows the Sign Up error message?
You have to use the #Html.ValidationSummary() inside the form to display the model validation errors.
Ex.
#using(Html.BeginForm())
{
#Html.ValidationSummary()
.. fields
}

ValidationSummary for server side errors is not working

Client side Validation and ValidationSummary is working fine for my project (MVC4 + Razor + Unobtrusive JS) but the Server side errors are not shown on my view and if there was any client side error, it does not get removed from the view (it does from the ModelState). I have tried on both Chrome14 and IE9
Server side errors are being added to the model as ModelState.AddModelError(string.Empty, ModelState.AllErrors()); and shown to the view as #Html.ValidationSummary(false).
Edit
Simple form submit is working fine, it shows multiple error messages returned from the server and updates error messages, but, ajax based form submit is not working error messages returned by ajax based form submit are not shown at all.
Here is a sample demonstration of how the request is being made
#*... View contents related to Master Model ...*#
#using (Ajax.BeginForm("ActionToAddRecord", new AjaxOptions()))
{
#Html.Action("ActionToAddRecord")
<input type="submit" value="Add Record"/>
}
#*... View contents related to Master Model ...*#
ActionToAddRecord is a partial view representing a model contained by a master model
Errors are returned as
[HttpGet]
public ActionResult ActionToAddRecord()
{
return View();
}
[HttpPost]
public ActionResult ActionToAddRecord(childModel model)
{
ModelState.AddModelError(string.Empty, "First error message");
ModelState.AddModelError(string.Empty, "Second error message");
return View(model);
}
Edit
I saw a similar functionality in templated MVC application by VS2010, the dialog based log in form. Error messages are returned as Json and then JS is being used to display them, IMO, seems like MS made Ajax based requests quite easy and concise (Ajax.BeginForm) but missing the error handling part. Right now i am not willing to use JS for this, there might be a better way to get this type of error handling dealt automatically.
Solved, with a small error.
Master View
#*Master View Contents*#
#using (Ajax.BeginForm("AddPaymentCurrency", new AjaxOptions { UpdateTargetId = "paymentCurrency" }))
{
<div id="paymentCurrency">
#{Html.RenderPartial("PaymentCurrency", Model.PaymentCurrencyNew);}
</div>
}
PaymentCurrency View
#*Model Editors*#
#Html.ValidationSummary(false)
<input type="submit" value="Add Payment Currency"/>
<div id="paymentCurrencyList" style="width:inherit; height:auto; overflow:auto;">
#Html.Action("PaymentCurrencyList")
</div>
Controller
[HttpPost]
public ActionResult AddPaymentCurrency(PaymentCurrency model)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError(string.Empty, ModelState.AllErrors());
return View("PaymentCurrency", model);
}
//Add login
return View("PaymentCurrency", model);
}
public ActionResult PaymentCurrencyList()
{
//var list = getList
return View(list);
}
small error
ValidationSummary is shown with fields highlighted and asterisk shown against them while adding invalid payment currency. Once a valid currency is added then ValidationSummary and asterisk is no more shown on invalid payment currency, just fields are highlighted.
Please help me to get it fixed, i would prefer not to change the current structure, otherwise i will start getting big error

How can I use multiple ajax forms with AntiForgery validation on the same MVC3 page?

When we have more than one possible form to post to the controller on the same cshtml page,
the Antiforgery validation does not work. We went through the MVC3 code and we found the problem is in this part of the code:
if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal)) {
// error: form token does not match cookie token
throw CreateValidationException();
}
The cshtml that we have is something like this:
#using (#Ajax.BeginForm()) {
#Html.AntiForgeryToken()
<input type="submit" class="buttonBlue" value="form1" />
}
#using (#Ajax.BeginForm()) {
#Html.AntiForgeryToken()
<input type="submit" class="buttonBlue" value="form2" />
}
Can you help me to fix this issue? We found that after removing one of the antiforgery tokens eveyrthing seems to work as expected.
We tried setting the machine key for the antiforgery and it didn't work either.
Regards.
In order to use the AntiForgeryToken multiple times, I do the following. First, at the top of my view, I add the following line:
ViewBag.__RequestVerificationToken = #Html.AntiForgeryToken().ToString();
Then, in each form where I need the token, I add the following:
#Html.Raw(ViewBag.__RequestVerificationToken)

Resources