ASP.NET MVC [Required] does not trigger - asp.net-mvc

As the title says my Required field does not trigger.
This is my ViewModel class its name is SignUpForm.cs
public class SignUpForm
{
[Required]
[StringLength(100,ErrorMessage="You must enter a your firstname!",
MinimumLength = 1)]
public string FirstName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "You must enter a your surname!",
MinimumLength = 1)]
public string SurName { get; set; }
}
This is my Razor view! Name of view is Step2.cshtml
#model MvcApplication2.Models.ViewModel.SignUpForm
#{
ViewBag.Title = "Step2";
}
<div id="content-header">
<h1 class="title">Complete your registration</h1>
</div>
<div id="content-area">
<h4>Fill in the form below to complete your registration
</h4>
#using(Html.BeginForm("testar","Interested", FormMethod.Post))
{
<h3>Personal information</h3>
<p class="app-label">Surname<span class="requiredField">*</span></p>
<div class="editor-label">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(m => m.FirstName)
</div>
<p class="app-label">Surname<span class="requiredField">*</span></p>
<div class="editor-label">
#Html.EditorFor(model => model.SurName)
#Html.ValidationMessageFor(m => m.SurName)
</div>
}
Source as Requested
<script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="/Scripts/modernizr-2.5.3.js" type="text/javascript"></script>
<link href="/Content/remigium.css" rel="stylesheet" />
<h3>Personal information</h3>
First name<span class="requiredField">*</span>
<div class="editor-label">
<input class="text-box single-line" data-val="true" data-val-length="You must enter a your firstname!" data-val-length-max="100" data-val-length-min="1" data-val-required="The FirstName field is required." id="FirstName" name="FirstName" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="FirstName" data-valmsg-replace="true"></span>
</div>
<p class="app-label">Surname<span class="requiredField">*</span></p>
<div class="editor-label">
<input class="text-box single-line" data-val="true" data-val-length="You must enter a your surname!" data-val-length-max="100" data-val-length-min="1" data-val-required="The SurName field is required." id="SurName" name="SurName" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="SurName" data-valmsg-replace="true"></span>
</div>

I was missing these script references, I added them and all was cool!
<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>

Related

ASP.NET MVC hidden field still getting name and passing to controller

I have this control that is hidden and the user need to check the input control for it to be show. I am getting the model fill with data and I wanted to see how I can only get data in the controller if it is selected ?
View
<input type="checkbox" value="91" name="chkProduct">
<label>Other</label>
<input type="hidden">
<input type="hidden" asp-for="Other">
<div id="sourceSection_91" style="">
<div class="row" id="ddRow_6" data-source="sourceSection_91">
<div class="col-md-11 !important">
<div class="form-group">
<label class="control-label source-label">Other</label>
<input class="form-control" id="enteredOtherSource" name="enteredOtherSource[0].Other" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="enteredOtherSource[0].Other" data-valmsg-replace="true"></span>
<input value="91" data-val="true" data-val-number="The field SourceId must be a number." data-val-required="The SourceId field is required." id="SourceId" name="enteredOtherSource[0].SourceId" type="hidden">
</div>
</div>
<div class="col-md-1 deleteBtn">
</div>
</div>
Model
public class OtherSourceModel
{
public int SourceId { get; set; }
public string Other { get; set; }
}
Controller
foreach (var ordermaterial in model.enteredOtherSource)
{
ProjectMaterialUse _SelectedOtherProjectMaterial = new ProjectMaterialUse();
_SelectedOtherProjectMaterial.Source = new Values();
_SelectedOtherProjectMaterial.Source.Value = ordermaterial.SourceId;
_SelectedOtherProjectMaterial.Other = ordermaterial.Other;
_SelectedOtherProjectMaterial.IntendedUse = new Values();
_SelectedOtherProjectMaterial.IntendedUse = model.selectedIntendedUseId;
_permissionrequestWeb.SelectedProjectMaterial.Add(_SelectedOtherProjectMaterial);
}

Data annotation validation does not work

I am developing an application in MVC using Smart Admin in which I use data annotations for validation purpose. My code is:
public class EmployeeDTO
{
[Key]
public int Id { get; set; }
[Required(ErrorMessage = "Name is required")]
[StringLength(50, ErrorMessage = "Name can accept maximum 50 characters.")]
[RegularExpression("^([a-zA-Z]{1}[a-zA-Z '-.(-,)-/&]*)$", ErrorMessage = "Please enter valid name.")]
public string Name { get; set; }
}
and my view is
<script src="~/SmartAdmin/js/libs/jquery-2.0.2.min.js"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#model HBSeworld.Admin.DTO.EmployeeDTO
#{
ViewBag.Title = "Create";
}
<section class="jarviswidget" id="wid-id-1" data-widget-editbutton="false" data-widget-custombutton="false">
<header>
<span class="widget-icon"><i class="fa fa-user"></i></span>
<h2>Create Employee</h2>
</header>
<div>
<div class="jarviswidget-editbox">
</div>
<section class="widget-body no-padding">
#using (Html.BeginForm("Create", "Employee", FormMethod.Post, new { #id = "order-form", enctype = "multipart/form-data", #class = "smart-form" }))
{
#Html.ValidationSummary(true)
<fieldset>
<div class="row">
<section class="label col col-2" style="text-align: right">
#Html.LabelFor(model => model.Name)
</section>
<section class="col col-4">
<label class="input">
<i class="icon-append fa fa-user"></i>
#Html.TextBoxFor(model => model.Name, null, new { #placeholder = "Enter Name" })
#Html.ValidationMessageFor(model => model.Name)
</label>
</section>
</div>
</fieldset>
<div class="pull-right" style="margin-right: 5px; margin-bottom: 10px;">
<input type="submit" id="create" value="Create" class="btn btn-primary" style="height: 25px; width: 45px;" />
<input type="button" style="height:25px; width:45px;" value="Cancel" class="btn btn-default" onclick="window.location.href='#Url.Action("index") '"/>
</div>
}
</section>
</div>
</section>
Now, my question is that, when I click on Create button, data annotation message is displayed properly but at the same time the control goes to controller, instead it should be on same view and have to display data annotation message. How to prevent this? Any solution?

MVC Template editors and post

I'm at a beginner with ASP.NET MVC 4 and I have a problem. Basically I have this controller:
public ViewResult Login()
{
return View(new LoginViewModel());
}
[HttpPost]
public ActionResult Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
if (authProvider.Authenticate(model.LoginUserName, model.LoginPassword))
{
return Redirect(Url.Action("Index", "Home"));
}
TempData["message"] = "Nome utente e/o password errati!!!";
return View();
}
return View();
}
That implements a simple login view. I created also a ViewModel:
public class LoginViewModel
{
[Required(ErrorMessage = "Il nome utente è obbligatorio")]
[UIHint("TextBoxLogin")]
public string LoginUserName { get; set; }
[Required]
public string LoginPassword { get; set; }
}
Finally I created the EditorTemplate:
#model string
<input name="#ViewData.TemplateInfo.HtmlFieldPrefix" id="#ViewData.TemplateInfo.HtmlFieldPrefix"data-validation="required" data-validation-error-msg="#ViewData["HelpMessage"]" value="#Model" />
So far so good. The problem is in the view. If I put this in the view:
#using(Html.BeginForm()) {
#Html.ValidationSummary(true)
#Html.EditorForModel()
<p><input type="submit" value="Log in" /></p>
}
It works like a charm (but it puts a lot of not wanted html into the page), in fact, when I click on the submit button it goes to the POST actionResult of the controller. If I put this:
#using (Html.BeginForm("Login","Account",FormMethod.Post))
{
<p class="username">
<label for="UserName">Nome utente</label>
#Html.EditorFor(m => m.LoginUserName, new { HelpMessage = "Il nome utente è obbligatorio!!!" });
</p>
<p class="password">
<label for="Password">Password</label>
#Html.EditorFor(m => m.LoginPassword)
</p>
<p>
<input type="submit" value="Log in" />
</p>
}
It does not go on the post actionresult but always on the Get one. I want to put this type of code (the last one) in wich I can setup exactly the html but I want that it goes on the POST Actionresult, can someone help me to understand why?
-----------------update----------------
Here is the HTML generated:
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<title>Title</title>
<meta name="robots" content="noindex,nofollow" />
<link href="/static/css/login.css" rel="stylesheet" type="text/css" />
<link href="/static/css/jquery_ui.css" rel="stylesheet" type="text/css" />
<!--[if lt IE 9]><link href="/static/css/lt_ie9.css" rel="stylesheet" type="text/css" /><![endif]-->
<script src="/static/js/jquery_1_10_2.js"></script>
<script src="/static/js/jquery_ui.js"></script>
<script src="/static/js/jquery_ui_function.js"></script>
</head>
<body>
<form>
<div id="top">
<div class="wrapped">
<div id="logo">TITLE</div>
</div>
</div>
<div id="content" class="user_student">
<div class="wrapped">
<div class="login_intro">
<h2>TEST</h2>
</div>
<div class="login_input">
<p id="error_messages"></p>
<h2>THIS ONE MAKES GET REQUEST</h2>
<form action="/Account/Login" method="post"> <p class="username"><label for="UserName">Nome utente</label>
<!--<input id="UserName" name="UserName" type="text"/>-->
<input name="LoginUserName" id="LoginUserName"data-validation="required" data-validation-error-msg="Il nome utente è obbligatorio!!!" />;
</p>
<p class="password"><label for="LoginPassword">Password</label>
<input class="text-box single-line" data-val="true" data-val-required="Il campo LoginPassword è obbligatorio." id="LoginPassword" name="LoginPassword" type="text" value="" />
</p>
<p><input type="submit" value="Log in" /></p>
</form> <p class="hidden">old</p>
</div>
<div class="login_footer">
<p>FOOTER</p>
</div>
</div>
</div>
<h2>THIS ONE MAKE POST REQUEST</h2>
<form action="/Account/Login?ReturnUrl=%2f" method="post"><div class="editor-label"><label for="LoginUserName">LoginUserName</label></div>
<div class="editor-field"><input name="LoginUserName" id="LoginUserName"data-validation="required" data-validation-error-msg="" /> <span class="field-validation-valid" data-valmsg-for="LoginUserName" data-valmsg-replace="true"></span></div>
<div class="editor-label"><label for="LoginPassword">LoginPassword</label></div>
<div class="editor-field"><input class="text-box single-line" data-val="true" data-val-required="Il campo LoginPassword è obbligatorio." id="LoginPassword" name="LoginPassword" type="text" value="" /> <span class="field-validation-valid" data-valmsg-for="LoginPassword" data-valmsg-replace="true"></span></div>
<p><input type="submit" value="Log in" /></p>
</form><script src="/static/form-validator/jquery.form-validator.min.js"></script>
<script src="/static/js/jquery_form_validator_function.js"></script>
</form>
</body>
</html>
Finally I figured out what is the problem...and of course it is the most stupid thing in the world.
In the rended code there is a open just after the body and, inside it, the form that MVC put from razor view.
Thanks for everyone for the help paricularly to #DavidG

Why isn't my jQuery validation working?

I have this in my Web.config:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
My view model:
public class CustomerViewModel
{
public Guid Id { get; set; }
[Required]
[DisplayName("First Name")]
public string FirstName { get; set; }
}
My view:
#using (Html.BeginForm(MVC.Customers.Edit(), FormMethod.Post, new { id = "edit-customer" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
...
</div>
}
And this is how the "form-group" div gets rendered:
<div class="form-group">
<label class="control-label col-md-2" for="FirstName">First Name</label>
<div class="col-md-10">
<input id="FirstName" class="form-control text-box single-line" name="FirstName" value="" type="text" data-val-required="The First Name field is required." data-val="true">
<span class="field-validation-valid text-danger" data-valmsg-replace="true" data-valmsg-for="FirstName"></span>
</div>
</div>
And I'm loading the jQuery scripts in this order:
<script src="/Scripts/jquery-1.10.2.js"></script>
<script src="/Scripts/jquery-ui-1.10.4.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
The form is shown using an ajax call when a button is clicked. It is also submitted with ajax. This all works fine when I'm not doing any validation. I added validation and I can't get it to trigger before the ajax call. Here's what I'm doing in the click handler that submits the form:
var formToSubmit = $('#' + attrData.formIdToSubmit);
if (!formToSubmit.valid()) {
return false;
}
formData = formToSubmit.serialize();
...
I expect formToSubmit.valid() to trigger the validation and return false when nothing is entered in the FirstName field. In practice it returns true and then validation fails on the server, ModelState.IsValid returns false as expected. In looking through the jQuery validation docs it looks like it expects a required attribute, like this:
<input id="FirstName" class="form-control text-box single-line" name="FirstName" value="" type="text" data-val-required="The First Name field is required." data-val="true" required>
If I use dev tools to add that and then click the submit button then the call to formToSubmit.valid() returns false as expected, however the error message doesn't end up in the span created by #Html.ValidationMessageFor, it ends up in a newly added label that looks like this:
<label for="FirstName" class="error">This field is required.</label>
What am I doing wrong?
Here is how I ended up fixing it:
var formToSubmit = $('#' + attrData.formIdToSubmit);
formToSubmit.removeData("validator")
.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(formToSubmit);
if (!formToSubmit.valid()) {
return;
}
formData = formToSubmit.serialize();
...

How does MVC populate the model when data is posted back

MVC is very clear on how data is sent to the browser. You go to a URL, it runs code to create a model, passes that typed model into a view, which then renders HTML based on the state of the model.
What I'm not finding so clear however is when a user submits a form on the page, how does MVC map that form post back to the model for use in the controller?
I'm guessing the magic happens somewhere in:
#Html.EditorFor(model => model.Title)
But I'm not understanding why....
I'm following Getting started with ASP.NET MVC 3. Which is where the code below is from for easy reference.
Controller:
public ActionResult Edit(int id)
{
Movie movie = db.Movies.Find(id);
return View(movie);
}
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
View:
#model MvcMovie.Models.Movie
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ReleaseDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ReleaseDate)
#Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Genre)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Genre)
#Html.ValidationMessageFor(model => model.Genre)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Price)
#Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Which generates:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script>
</head>
<body>
<div class="page">
<header>
<div id="title">
<h1>MVC Movie App</h1>
</div>
...
</header>
<section id="main">
<h2>Edit</h2>
<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
<form action="/Movies/Edit/4" method="post"> <fieldset>
<legend>Movie</legend>
<input data-val="true" data-val-number="The field ID must be a number."
data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />
<div class="editor-label">
<label for="Title">Title</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" />
<span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="ReleaseDate">ReleaseDate</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-required="The ReleaseDate field is required."
id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" />
<span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Genre">Genre</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" />
<span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Price">Price</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number."
data-val-required="The Price field is required." id="Price" name="Price" type="text" value="9.99" />
<span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
<div>
Back to List
</div>
</section>
<footer>
</footer>
</div>
</body>
</html>
MVC just matches the public properties of a model against values in the FormsCollection object of the same name. If there is a match of name and type, then an instance of the model is created and the values copied into those properties.
This process is called Model Binding, and you can create custom Model Binders.
The process has little to do with EditorFor directly, although EditorFor uses templates that make sure to name the form inputs in a manner that the model binder can understand.
ASP.Net MVC is based on Convention over Configuration concept. So most of the things work like magic but underneath mechanisms are there to work in default as well as to customize if you want.
The term Model Binding is the keyword you should check out to understand this.
Check here
6-tips-for-asp-net-mvc-model-binding
MVC uses whats referred to as a Model Binder to take post back values and recreate a model.
Here is a good read: Models and Validation in ASP.NET MVC

Resources