Validationsummary not showing errors generated in the controller - c#

When I generate an error in the controller and return back the view, the validation summary doesn't show up. All works fine for errors generated from the view itself. How can we make the summary show up?
Here's the simplified controller method:
[HttpPost]
public ActionResult EditProfil(Prospect prospect)
{
ModelState.AddModelError(string.Empty, "You have an error");
if (!ModelState.IsValid)
return View("Edit", prospect);
return Json(prospect);
}
And the view looks like this:
#model Prospect
#{
ViewBag.Title = "Profil du prospect";
Layout = null;
}
//Some javascript and CSS unrelated to validations
#using (Html.BeginForm())
{
#Html.ValidationSummary(false)
//My form controls...
}

edit
the problem is a combination of
ModelState.AddModelError(string.Empty, "You have an error");
and
#Html.ValidationSummary(false)
an empty string is "" which is interperted as a property name, event thought it's an empty string. Either remove the boolean false from rendering the summary or pass null to the modelstate bag.

With MVC4, passing null to ModelState.AddModelError is invalid. This actually worked using:
ModelState.AddModelError(string.Empty, "Error");
and
#Html.ValidationSummary(false)
It turned out that I had two problems.
I was returning the wrong view.
I was using an Ajax call and not updating the div.
The following solved it for me:
<div id="results">
#{
using (Ajax.BeginForm("CreateLookupTable", "Lookup", new AjaxOptions { HttpMethod = "POST", OnSuccess = "FormSuccess()", UpdateTargetId ="results" }))
{
#Html.ValidationSummary(false)
// Form
}
</div>

Related

Resending a Model resets values in asp.net mvc?

This is my View:
#model test2.Models.ChatModel
#{
ViewBag.Title = "Channel";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<center>
<h2>Channel: #Model.channelName</h2>
#{
foreach (string line in Model.chatLog) {
<div>#line</div>
}
}
<br />
#using (Html.BeginForm("sendMessage", "Home", FormMethod.Post)) {
#Html.TextBoxFor(model => model.message)
<button type="submit"> Send Message </button>
}
</center>
Here is my Controller:
public ActionResult sendMessage(ChatModel model) {
//send message somewhere
//this is not working
return RedirectToAction("Channel", "Home", new { channel = model.channelName });
//this is working
return RedirectToAction("Channel", "Home", new { channel = "test" });
}
The error happens in the redirectToAction method. Somehow "model.channelName" is empty, but #Model.channelName in my view is correctly displaying the channel name.
It looks like when you send a Model to a view, and "resend" this model back to a controller, the informations are lost.
Is there an easy way to solve this?
PS Step by step:
Model gets channelName
Model is send to view
View correctly displays data from model
adding message to Model
sending model to controller
model does NOT contain information from step 1
You need to include model.channelName in the form. Try adding a:
#Html.HiddenFor(model => model.channelName)
Anything not posted by the form, will be null in your model (including your chatlog)
Actually the values model properties should be rendered as input elements within the form that is posted back to controller action. The properties which are not included would loose their values.
What you can do is create a hidden field for those to post :
#using (Html.BeginForm("sendMessage", "Home", FormMethod.Post)) {
#Html.TextBoxFor(model => model.message)
#Html.HiddenFor(model => model.channelName)
<button type="submit"> Send Message </button>
}
You would need to add same way other properties too that are posting null at action and you need those for some processing.
Hope it helps.

Doesn't show view from controller even debugger goes inside View

I am new in MVC .net. I am not able to call view from controller. I have debug the flow. It goes to view successfully but doesn't show view on screen.
Controller name: Downloads
Action name: MakePayment
Redirect view: Success //success is view of View/Downloads/Success.cshtml
Code: DownloadsController
[HttpPost]
public ActionResult MakePayment(Downloads CCM)
{
if (true)
{
return View("Success");
}
else
{
return View("Failure");
}
}
View
#{
ViewBag.Title = "Success";
}
<h2>Your transaction has been completed successfully.</h2>
Method that I use to call the ActionResult MakePayment. I had use Ajax here because I wanted to call javascript function before form get submit.
View: Index.cshtml
#using (Ajax.BeginForm("MakePayment", "Downloads", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, OnBegin = "payByCreditCard" }))
{
//submit button
}
According to the return View("Success");, it should call the view. In fact when I debug the flow, it goes to Success view but doesn't display the view on screen. It keeps old view on screen.
Degug route after success: _ViewStart-->Success.cshtml-->_Layout.cshtml.
Can anybody suggest me if I am missing something?
Since you are making an ajax call using Ajax.BeginForm helper method, you need to specify where the response (of the ajax call) to be replaced in the DOM. You can specify that using the UpdateTargetId property
#using (Ajax.BeginForm("MakePayment", "Downloads", new AjaxOptions { HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId="YourDivToShowResult"
OnBegin = "payByCreditCard" }))
{
<div id="YourDivToShowResult"></div>
<input type="submit" />
}
Since this is an ajax call, It will not do a redirect. Instead,it will update the content of the div (with Id YourDivToShowResult) in the same page with response coming back which is the markup returned by Success view.
Also since we are showing a partial page update, you might consider returning a partial view.
[HttpPost]
public ActionResult MakePayment(Downloads CCM)
{
if (everything is good)
{
return PartialView("Success");
}
else
{
return PartialView("Failure");
}
}
This will return the markup from either of those views without the layout.
If you want to go to other view you have to redirect the page like:
return RedirectToAction("Success", "Downloads");

DropDown Menu using IEnumerable SelectList

I am getting the following error when trying to select an item from my drop down list and submit this.
An exception of type 'System.InvalidOperationException' occurred in
System.Web.Mvc.dll but was not handled in user code Additional
information: There is no ViewData item of type
'IEnumerable' that has the key 'RoleName'.
If anyone can help me figure out how to fix this error I would really appreciate it as I haven't been able to fix it yet and been stuck for quite a long time and google hasn't provided a solution yet!
This is my controller code
[AllowAnonymous]
public ActionResult Index()
{
var roles = context.Roles.ToList();
return View(roles);
}
[Authorize(Roles = "canEdit")]
public ActionResult ManageUserRoles()
{
var list = context.
Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
ViewBag.Roles = list;
return View();
}
public ActionResult RoleAddToUser(string UserName, string RoleName)
{
ApplicationUser user = context.Users.FirstOrDefault(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
UserManager.AddToRole(user.Id, RoleName);
}
return View("ManageUserRoles");
}
This is my ManageUserRoles View
#{
ViewBag.Title = "ManageUserRoles";
}
<h2>Manage User Roles</h2>
#Html.ActionLink("Create New Role", "Create") | #Html.ActionLink("View User Roles", "Index")
<hr />
<h2>Role Add to User</h2>
#using (Html.BeginForm("RoleAddToUser", "Roles"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<p>
User Name : #Html.TextBox("UserName")
Role Name: #Html.DropDownList("RoleName", (IEnumerable<SelectListItem>) ViewBag.Roles, "Select ...")
</p>
<input type="submit" value="Save" />
}
<hr />
Problem is (I assume) that you are visiting View("ManageUserRoles") from your ActionResult RoleAddToUser and not from ManageUserRoles. So ViewBag does not exists.
return View("ManageUserRoles");
starts to render view. However on the view you have dropdown which wants ViewBag.Roles ... but ... where do you set data into it? This exception is thrown because ViewBag.Roles just not exist.
If you want run ActionResult ManageUserRoles before returning the view, you have to call redirect.
return RedirectToAction("ManageUserRoles");
If you want render view without execute code in that method, you have to create ViewBag.Roles in RoleAddToUser. Please, note that ViewBag data are deleted after every request.
Verify that your model (whether its a domain model or some other viewmodel) has a field of string type called "RoleName", this needs to match the first argument of your DropDownList call so the page knows what variable to post the data back in on form submit.

MVC 4 - Captcha.Mvc

I have a Captcha control for my MVC 4 page and I cannot get it to show a message if the input was incorrect. I'm used to doing things through jquery and on success do something, but when I do something like that here I lose the ModelState.IsValid.
So, when I run this code the Captcha control loads fine on the page it shows the 5 letters in an image with a line that says 'Refresh' and a textbox beneath that for input with a submit button on my index page to post to the controller.
When I get input wrong it refreshes the image with no message saying anything was wrong, I know it was wrong because my controller says ModelState.IsValid is false but I want to load a new image and display that the input was incorrect.
When I get input correct it refreshes the image still with no message or anything. I want it to stay there and say that the input was correct and disable the textbox.
My question: How can I do what I described above?
My code is below:
Controllers/HomeController.cs
using System.Web.Mvc;
using CaptchaDemo.MVC4.ViewModels;
using CaptchaMvc;
using CaptchaMvc.Attributes;
using CaptchaMvc.Infrastructure;
namespace CaptchaDemo.MVC4.Controllers
{
public class HomeController : Controller
{
// GET: /Home/
public ActionResult Index()
{
CaptchaUtils.CaptchaManager.StorageProvider = new CookieStorageProvider();
ViewBag.Title = "Captcha MVC 4 Demo";
return View();
}
public ActionResult _Captcha()
{
CaptchaViewModel model = new CaptchaViewModel();
return View(model);
}
public ActionResult AjaxForm()
{
return View(new CaptchaViewModel());
}
[HttpPost, CaptchaVerify("Captcha is not valid")]
public ActionResult AjaxForm(CaptchaViewModel model)
{
if (ModelState.IsValid)
{
ModelState.Clear();
TempData["Message"] = "Message: captcha is valid.";
model.strMessage = "efefwf";
if (Request.IsAjaxRequest())
return PartialView("_Captcha", model);
//return Json(model, JsonRequestBehavior.AllowGet);
return View(model);
}
TempData["ErrorMessage"] = "Error: captcha is not valid.";
if (Request.IsAjaxRequest())
return PartialView("_Captcha", model);
return View(model);
}
}
}
ViewModels/CaptchaViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CaptchaDemo.MVC4.ViewModels
{
public class CaptchaViewModel
{
public string strMessage { get; set; }
}
}
Views/Home/Index.cshtml
#using (Html.BeginForm("AjaxForm", "Home", FormMethod.Post, new { #id = "AjaxCaptchaForm", #class = "ajax" }))
{
<div id="update">#Html.Partial("_Captcha")</div>
<input type="submit" />
}
<script type="text/javascript">
$(document).ready(function () {
$('#AjaxCaptchaForm').submit(function () {
$.post($(this).attr("action"), $(this).serialize(), function (results) {
$("#update").html(results);
});
return false;
});
});
</script>
Views/Shared/_Captcha.cshtml
#using CaptchaMvc.HtmlHelpers
#model CaptchaDemo.MVC4.ViewModels.CaptchaViewModel
#Html.ValidationSummary(true)
#Html.ValidationMessageFor(model => model.strMessage)
#Html.Captcha(5)
<span>#Model.strMessage</span>
In case someone still need help with this:
There are two options one:
#Html.Captcha("Refresh", "Captcha is not valid "
, 4, "The Captcha is required", true)
The last true set the bool addValidationSpan.
Another option:
<span class="field-validation-valid text-danger" data-valmsg-for="CaptchaInputText" data-valmsg-replace="true" id="vali_CaptchaInputText"></span>
<span class="field-validation-valid text-danger" data-valmsg-for="CaptchaDeText" data-valmsg-replace="true" id="vali_CaptchaDeText"></span>
Also the <script src="~/Scripts/jquery-2.1.4.js"></script> need to be loaded before this line is rendered.
#Html.Captcha(5) renders an input with id="CaptchaInputText". To display a native warning message you need to append you model with CaptchaInputText property and add
#Html.ValidationMessageFor(m => m.CaptchaInputText, String.Empty, new { #class = "validation-error", #style = "color:red;" })
into your view.

Checking validation in view

I am working with an MVC application.
My code lies like the following:-
if(//there are errors then display validation summary)
{
<div class="error">#Html.ValidationSummary(true, "There was an error!")<div>
}
#using (Html.BeginForm("FoundSimilarAccounts", "Account", FormMethod.Post, new { id = "contactform" }))
{
}
I just want to know what can be the if condition.
I only want to display that when their would be an error or their is something in the validation summary.
Thanks
You can inspect the IsValid property of the ModelState of the ViewData:
#if(!ViewData.ModelState.IsValid)
{
<div class="error">#Html.ValidationSummary(true, "There was an error!")<div>
}

Categories

Resources