I am trying to get what I think is a simple example of using DataAnnotations on a model to drive the client side validation as well.
Here is my model...
public class Person
{
[Required(ErrorMessage = "First Name Required")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name Required")]
public string LastName { get; set; }
}
Here is my controller...
public class FriendsController : Controller
{
public ActionResult Create()
{
Person newFriend = new Person();
return View(newFriend);
}
[HttpPost]
public ActionResult Create(Person friendToCreate)
{
if (ModelState.IsValid)
{
// todo -- do something here
return Redirect("/");
}
// Invalid - redisplay form with errors
return View(friendToCreate);
}
}
and here is my view...
#model MvcApplication4.Models.Person
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.4.4.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/MicrosoftMvcValidation.js")" type="text/javascript"></script>
</head>
<body>
<h2>
Create</h2>
#{Html.EnableClientValidation();}
#using (Html.BeginForm())
{
<fieldset>
<p>
#Html.LabelFor(m => m.FirstName)
#Html.TextBoxFor(m => m.FirstName)
#Html.ValidationMessageFor(m => m.FirstName)
</p>
<p>
#Html.LabelFor(m => m.LastName)
#Html.TextBoxFor(m => m.LastName)
#Html.ValidationMessageFor(m => m.LastName)
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
</body>
</html>
The server side validation works just fine and the validation error messages appear as expected. However, I am not getting the client side validation to work. Is there something obvious that I am missing to make the client side validation appear?
Did you enabled Client side Validation on your web.config file?
You can do it directly on the web.config file adding a couple of flags inside the appSetting section
<configuration>
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
</configuration>
or you can do it using pure c# code
HtmlHelper.ClientValidationEnabled = true;
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
I recommend you read Brad Wilson's article Unobtrusive Client Validation in ASP.NET MVC 3
Related
I have a really wierd issue with MVC.
My models keeps getting submitted empty.
And it's probably really simple, but I just can't find the issue.
My model looks like this:
public class LoginModel
{
public string Username;
public string Password;
}
My controller like this:
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LoginModel loginTest)
{
if (loginTest.Username != "x" && loginTest.Password != "y")
{
ModelState.AddModelError("a", "Login failed.");
return View(loginTest);
}
else
{
return RedirectToAction("Home", "Welcome");
}
}
And the view is also very simple, like this.
#model LoginSolution.Models.LoginModel
#{
Layout = null;
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Login</title>
</head>
<body>
#using (Html.BeginForm("Login", "Home"))
{
<div> <span>Username : </span>
#Html.EditorFor(model => model.Username)
<br />
<span>Password : </span>
#Html.EditorFor(model => model.Password)
<br />
#Html.ValidationSummary()
<br />
<input type="submit" value="Login" name="Login" />
</div>
}
</body>
</html>
This is not a question about security or best practice.
This is just a question regarding why the model keeps returning itself as empty upon submitting.
Your model contains fields, not properties (no getter/setter) so the model binder cannot set the values. Change your model to
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}
I have a really wierd issue with MVC.
My models keeps getting submitted empty.
And it's probably really simple, but I just can't find the issue.
My model looks like this:
public class LoginModel
{
public string Username;
public string Password;
}
My controller like this:
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LoginModel loginTest)
{
if (loginTest.Username != "x" && loginTest.Password != "y")
{
ModelState.AddModelError("a", "Login failed.");
return View(loginTest);
}
else
{
return RedirectToAction("Home", "Welcome");
}
}
And the view is also very simple, like this.
#model LoginSolution.Models.LoginModel
#{
Layout = null;
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Login</title>
</head>
<body>
#using (Html.BeginForm("Login", "Home"))
{
<div> <span>Username : </span>
#Html.EditorFor(model => model.Username)
<br />
<span>Password : </span>
#Html.EditorFor(model => model.Password)
<br />
#Html.ValidationSummary()
<br />
<input type="submit" value="Login" name="Login" />
</div>
}
</body>
</html>
This is not a question about security or best practice.
This is just a question regarding why the model keeps returning itself as empty upon submitting.
Your model contains fields, not properties (no getter/setter) so the model binder cannot set the values. Change your model to
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}
I have a really wierd issue with MVC.
My models keeps getting submitted empty.
And it's probably really simple, but I just can't find the issue.
My model looks like this:
public class LoginModel
{
public string Username;
public string Password;
}
My controller like this:
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LoginModel loginTest)
{
if (loginTest.Username != "x" && loginTest.Password != "y")
{
ModelState.AddModelError("a", "Login failed.");
return View(loginTest);
}
else
{
return RedirectToAction("Home", "Welcome");
}
}
And the view is also very simple, like this.
#model LoginSolution.Models.LoginModel
#{
Layout = null;
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Login</title>
</head>
<body>
#using (Html.BeginForm("Login", "Home"))
{
<div> <span>Username : </span>
#Html.EditorFor(model => model.Username)
<br />
<span>Password : </span>
#Html.EditorFor(model => model.Password)
<br />
#Html.ValidationSummary()
<br />
<input type="submit" value="Login" name="Login" />
</div>
}
</body>
</html>
This is not a question about security or best practice.
This is just a question regarding why the model keeps returning itself as empty upon submitting.
Your model contains fields, not properties (no getter/setter) so the model binder cannot set the values. Change your model to
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}
I have setup a little test project that I hope will explain my problem.
I have a parent class that has a property containing all its children of type Child. In the MVC view I list all the children in a table and to have the form post back my children and map them to the parent property automatically I render them like:
#Html.TextBox(string.Format("Children[{0}].ChildName", childIndex), child.ChildName)
In the controller I have marked property ChildName to be required. The problem I have is that jquery unobtrusive validation does not emit any data validation attributes. Everything validates nice on the server but not on the client (obviously because there are no attributes for jquery validation to find on these inputs).
Please have a look at the code:
VIEW
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
<form action="#Url.Action("Save")" method="post">
#Html.TextBox("Name", (string)Model.Name)
<table>
<tr><td>Child name</td></tr>
#{var childIndex = 0;}
#foreach (var child in (List<GridValidationTest.Controllers.Child>)Model.Children)
{
<tr><td>#Html.TextBox(string.Format("Children[{0}].ChildName", childIndex), child.ChildName)</td></tr>
childIndex++;
}
</table>
<br /><button>Submit</button>
</form>
</div>
</body>
</html>
CONTROLLER
namespace GridValidationTest.Controllers
{
public class Parent
{
[Required]
public string Name { get; set; }
public IList<Child> Children { get; set; }
}
public class Child
{
[Required]
public string ChildName { get; set; }
}
public class MyController : Controller
{
//
// GET: /My/
public ActionResult Index()
{
var parent = new Parent { Name = "Parent name" };
parent.Children = new List<Child>
{
new Child {ChildName = "First child"},
new Child {ChildName = "Second child"}
};
return View("Index", parent);
}
public ActionResult Save(Parent parent)
{
return View("Index", parent);
}
}
}
The client validation on property Name of Parent class works fine as expected.
How should I render the children to have client-side validation to work as I expect?
You need to bind the fields in your view to your model. Instead of using:
#Html.TextBox(string.Format("Children[{0}].ChildName", childIndex), child.ChildName)
Use
#Html.TextBoxFor(model => model.Children[childIndex])
#Html.ValidationMessageFor(model => model.Children[childIndex])
Also make sure you are including the right jquery javascript files on your page. Something like:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.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>
Also make sure that in your web config you have ClientValidationEnabled and UnobtrusiveJavaScriptEnabled turned on like so:
<appSettings>
....
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
....
</appSettings>
I'm trying to validate this model:
public class LogonModel
{
[Required(ErrorMessage="Username is required")]
public string Username { get; set; }
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
}
In this action:
public ActionResult Logon()
{
LogonModel model = new LogonModel();
return View(model);
}
In this View:
#model POCModelValidation.Models.LogonModel
#{
ViewBag.Title = "Index";
}
<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>
<h2>Index</h2>
#using (Html.BeginForm())
{
<h3>username</h3>
#Html.EditorFor(model => model.Username)
<h3>#Html.ValidationMessageFor(model => model.Username)</h3>
<br />
<h3>Password</h3>
#Html.EditorFor(model => model.Password)
<h3>#Html.ValidationMessageFor(model => model.Password)</h3>
<br />
<h3>Email</h3>
#Html.EditorFor(model => model.Email)
<h3>#Html.ValidationMessageFor(model => model.Email)</h3>
<input type="submit" value="Submit"/>
}
..And I can't figure out the pattern in which it works, but it never works for the whole 3 fields. Other than that, if I fill, leave, then go back and delete the content of the fields enough times, it eventually works for all of them, but rarely on the first time, and never for all of them at the same time.
I do have these line in my web.config
...
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
...
And in _Layout:
...
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
...
Any ideas?
Load up Fiddler http://www.fiddler2.com/fiddler2/ and ensure the scripts are properly getting loaded. If they aren't, validation just won't work.
Please add the following line to your code
<%Html.EnableClientValidation();%>
#using (Html.BeginForm())
**Your code**