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>
}
Related
How to change the language for "The value 'some value' is not valid for 'some property'" validation error?
Can anyone help? I want to translate the error in the picture to Russian Error. I read much sites, try to use RegularExpression, but it doesn't help
may be I don't correctly understand how to do that?
I need only translate the error, not need to change the culture.
In web.config:
<globalization culture="en" uiCulture="en" />
My entity with data annotations attributes:
public class Player
{
/* Some other properties */
[Required(ErrorMessage = "Укажите среднее количество блокшотов")]
[Range(0, 10.0, ErrorMessage = "Недопустимое значение, до 10")]
public float BlockPerGame { get; set; }
/* Some other properties */
}
My View:
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.Id)
<div class="box-form">
/* Some other properties */
<div class="text-style-roboto form-group">
<label>Среднее количество блокшотов</label>
#Html.TextBoxFor(m => m.BlockPerGame, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.BlockPerGame)
</div>
/* Some other properties */
<div class="form-group">
<button type="submit" class="button button-create" id="button-create">Добавить</button>
#Html.ActionLink("Отмена", "Index", null, new { #class = "button button-cancel", id = "button-cancel" })
</div>
</div>
}
And my Controller:
public class AdminController : Controller
{
/*Some other methods*/
[HttpPost]
public async Task<ActionResult> Edit(Player player, string ChoosingTeam)
{
if (ModelState.IsValid)
{
if (ChoosingTeam != string.Empty)
{
try
{
player.TeamId = int.Parse(ChoosingTeam);
await repository.SavePlayerAsync(player);
TempData["message"] = string.Format("Игрок {0} {1} сохранены", player.Name, player.Surname);
return RedirectToAction("Index");
}
catch (Exception exc)
{
Console.WriteLine(exc.Message);
}
}
}
IEnumerable<SelectListItem> list = new SelectList(repository.Teams, "Id ", "Name");
ViewBag.ChoosingTeamName = list;
return View(player);
}
}
When you enter an invalid value for a property, if model binder cannot bind that value to the property, the model binder sets an error message for that property. It's different from data-annotations model validation. It's in fact model binder validation error.
Localizing or Changing Default Model Binding Error Messages
Model binding error messages are different from model validation messages. To customize or localize them, you need to create a global resource and register it in Application_Start for DefaultModelBinder.ResourceClassKey.
To do so, follow these steps:
Go to Solution Explorer
Right click on project → Add → ASP.NET Folder → Choose App_GlobalResources
Right click on App_GlobalResources → Choose Add New Item
Choose Resource File and set the name to ErrorMessages.resx
In the resource fields, add the following keys and values and save the file:
PropertyValueInvalid: The value '{0}' is not valid for {1}.
PropertyValueRequired: A value is required.
Note: If you want to just customize the messages, you don't need any language-specific resource, just write custom messages in the ErrorMessages.resx and skip next step.
If you want localization, for each culture, copy the resource file and paste it in the same folder and rename it to ErrorMessages.xx-XX.resx. Instead of xx-XX use the culture identifier, for example fa-IR for Persian language
and enter translation for those messages, for example for ErrorMessages.fa-IR.resx:
PropertyValueInvalid: مقدار '{0}' برای '{1}' معتبر نمی باشد.
PropertyValueRequired: وارد کردن مقدار الزامی است.
Open Global.asax and in Application_Start, paste the code:
DefaultModelBinder.ResourceClassKey = "ErrorMessages";
ASP.NET CORE
For ASP.NET Core read this post: ASP.NET Core Model Binding Error Messages Localization.
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.
I render a Validation Summary in my MVC 5 App as below:
#Html.Partial("_ValidationSummary", #ViewData.ModelState)
and the Partial View code is as below:
#model ModelStateDictionary
<div class="#(Html.ViewData.ModelState.IsValid ? "validation-summary-valid" : "validation-summary-errors") panel panel-danger"
data-valmsg-summary="true">
<div class="panel-heading">
Please, correct the following errors:
</div>
<div class="panel-body">
<ul>
#foreach (var modelError in Model.SelectMany(keyValuePair => keyValuePair.Value.Errors))
{
<li>#modelError</li>
<li>#modelError.ErrorMessage</li>
}
</ul>
</div>
</div>
This is working quite nicely - in that the error messages display for fields that are in error.
However - The name of the Field on the model that is error is not added - so I have a field for mobile number and for home phone and for work phone. If i put abc into each field then in my validation summary I get 3 error messages saying "Phone Number is Invalid" but I would like to add the field to the error message so that I can add that to the error message to the User will know which of the fields is in error?
Is there an easy way to tweak my current code to achieve this?
You can use the ModelMetaData, found in the ViewData, to retrieve the display name of the key :
#foreach (var key in ViewData.ModelState.Keys)
{
var modelState = ViewData.ModelState[key];
var property = ViewData.ModelMetadata.Properties.FirstOrDefault(p => p.PropertyName == key);
if (property != null)
{
var displayName = property.DisplayName;
foreach (var error in modelState.Errors)
{
<li>#displayName: #error.ErrorMessage</li>
}
}
else
{
foreach (var error in modelState.Errors)
{
<li>#error.ErrorMessage</li>
}
}
}
Make sure you add
#using System.Linq
at the top of the view.
You can also use a <label> to allow the user to click on the display name to automatically focus the input field:
<li><label for="#key">#displayName</label>: #error.ErrorMessage</li>
You can try below LINQ query
foreach (var modEr in ModelState.Select(st => new { Field = st.Key, Errors = st.Value.Errors.Select(er => er.ErrorMessage) }))
{
//modEr.Field //Field name
//modEr.Errors //List of errors
}
Additionally there is a MVC defined HTML helper to show validation summary, refer
http://msdn.microsoft.com/en-us/library/system.web.mvc.html.validationextensions.validationsummary(v=vs.118).aspx
You can just use data annotations against each of the fields in your model.
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>
I have a simple form on an ASP.NET MVC site that I'm building. This form is submitted, and then I validate that the form fields aren't null, empty, or improperly formatted.
However, when I use ModelState.AddModelError() to indicate validation errors from my controller code, I get an error when my view is re-rendered. In Visual Studio, I get that the following line is highlighted as being the location of the error:
<%=Html.TextBox("Email")%>
The error is the following:
NullReferenceException was unhandled by user code - object reference not set to an instance of an object.
My complete code for that textbox is the following:
<p>
<label for="Email">Your Email:</label>
<%=Html.TextBox("Email")%>
<%=Html.ValidationMessage("Email", "*") %>
</p>
Here's how I'm doing that validation in my controller:
try
{
System.Net.Mail.MailAddress address = new System.Net.Mail.MailAddress(email);
}
catch
{
ModelState.AddModelError("Email", "Should not be empty or invalid");
}
return View();
Note: this applies to all of my fields, not just my Email field, as long as they are invalid.
That's a horrible bug/feature (call in whatever) in ASP.NET MVC the helper that you may fix by calling SetModelValue like this:
ModelState.AddModelError("Email", "Should not be empty or invalid");
ModelState.SetModelValue("Email", new ValueProviderResult("raw value", "attempted value", CultureInfo.InvariantCulture));
By the way is there any reason you would write all this code when you could simply annotate your view model:
public class SomeViewModel
{
[RegularExpression("Some bulletproof regex you could google to validate email address", ErrorMessage = "Should not be empty or invalid")]
public string Email { get; set; }
}
and leave the data binder do the heavy lifting.
I am unable to reproduce.
Action
[HttpPost]
public ActionResult Index(string email)
{
if (string.IsNullOrEmpty(email))
{
ModelState.AddModelError("Email", "Should not be empty or invalid");
}
return View();
}
View
<%using (Html.BeginForm() { %>
<p>
<label for="Email">
Your Email:</label>
<%=Html.TextBox("Email")%>
<%=Html.ValidationMessage("Email", "*") %>
<input type="submit" />
</p>
<%} %>