How to customize ASP.net MVC jquery unobtrusive validation message display - asp.net-mvc

by default MVC use jquery unobtrusive validation lib to show validation message at client side. suppose i have small form with two textbox for first name and last name. when click submit button then client side validation will fire and display all validation message at once. but i want to display validation message one by one. now tell me where to customize the code and what code need to add or modify in js to make it possible.
here is my small sample code
namespace MVC_myfirst_Mvcapplication.Models
{
public class Person
{
public int ID { get; set; }
[Required]
[StringLength(30)]
public string First { get; set; }
[Required]
[StringLength(30)]
public string Last { get; set; }
public DateTime Birthdate { get; set; }
}
public class PersonContext : DbContext
{
public DbSet<Person> People { get; set; }
}
}
Controller : PersonController.cs
public class PersonController : Controller
{
PersonContext db = new PersonContext();
//
// GET: /Person/
public ActionResult Index()
{
var People = db.People.ToList();
return View(People);
}
//
// GET: /Person/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Person/Create
[HttpPost]
public ActionResult Create(Person Person)
{
db.People.Add(Person);
db.SaveChanges();
return RedirectToAction("Index");
}
}
View:
#model MVC_myfirst_Mvcapplication.Models.Person
#{
ViewBag.Title = "Create";
}
<h2>Create</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>Person</legend>
<div class="editor-label">
#Html.LabelFor(model => model.First)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.First)
#Html.ValidationMessageFor(model => model.First)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Last)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Last)
#Html.ValidationMessageFor(model => model.Last)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Birthdate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Birthdate)
#Html.ValidationMessageFor(model => model.Birthdate)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
tell me which code i need to change in js to show validation message one-by-one in a specific div? thanks

Related

why my checkboxes arent generated?

i have the following controller that calls view with template that generates a set of checkboxes
The controller / Action
public class CompoundsController : Controller
{
//
// GET: /Compounds/
testdbDBContext db = new testdbDBContext();
public ActionResult Index()
{
var comps = db.Compounds.Select(e => new CompoundModel { Id=e.Id, Code=e.Code, Name=e.Name, IsSelected = e.IsSelected }).ToList();
return View(new ChemicalsVM { cModel = comps});
}
}
The view
#model mvca1.Models.ChemicalsVM
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>ChemicalsVM</legend>
<div class="editor-label">
#Html.LabelFor(model => model.SName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SName)
#Html.ValidationMessageFor(model => model.SName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DName)
#Html.ValidationMessageFor(model => model.DName)
</div>
<div class="editor-label">
#Html.Label("Chemicals")
</div>
<div class="editor-field">
#Html.EditorFor(x=>x.cModel)
#Html.ValidationMessageFor(model => model.cModel)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
the template is:
#model mvca1.Models.CompoundModel
#{
ViewBag.Title = "rmplCompoundDB";
}
#Html.HiddenFor(x=>x.Id)
#Html.HiddenFor(x=>x.Code)
#Html.CheckBoxFor(x=>x.IsSelected, (Model.IsSelected)? new {#checked="checked"}:null)
#Html.LabelFor(x=>x.Name)
when i ran the code instead of generating checkboxes with labels it displays the id numbers (that should be hidden)
here is the video of what happens https://youtu.be/1Z2fwfBgyn8
why it does not display the checkboxes as expected?
UPDATE:
here is my ChemicalsVM
public class ChemicalsVM
{
public int Id { get; set; }
public string SName { get; set; }
public string DName { get; set; }
public List<CompoundModel> cModel { get; set; }
public ChemicalsVM()
{
cModel = new List<CompoundModel>();
}
}
here is the CompoundModel class
public class CompoundModel
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
The html being rendered means the ViewEngine is not finding the EditorTemplate. The template must be named the same as the class (i.e. CompoundModel.cshtml) and be located in either the /Views/Shared/EditorTemplates or /Views/Compounds/EditorTemplates folders.

How do you post data to joined tables - Using EF 5, ASP.NET MVC 4

I am new to MVC 4 and up to this point I have been retrieving data from one table and saving back to the same table. Now I have data from joined tables and need to save back to the same joined tables. I created a new model and created the get controller but when I try to save I get an error. Any constructive help would be appreciated.
Model
public partial class JoinClass
{
public string Name { get; set; }
public int EEID { get; set; }
public string Category { get; set; }
public int Points { get; set; }
public string Programs { get; set; }
public DateTime EntryDate { get; set; }
public DateTime Quarter { get; set; }
}
Controller
public ActionResult Create()
{
ViewBag.VBQuarter = new SelectList(db.Quarter2, "Id_Quarter2", "Quarter");
ViewBag.VBEEID = new SelectList(db.Users2, "Id_Users2", "EEID");
ViewBag.FK_Programs = new SelectList(db.Programs, "Id_Programs", "Programs");
ViewBag.EntryDate = DateTime.Now;
return View();
}
//
// POST:
[HttpPost]
public ActionResult Create(JoinClass joinclass)
{
if (ModelState.IsValid)
{
db.JoinClass.Add(joinclass);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(joinclass);
}
View
#model 2014_V4.Models.JoinClass
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
<fieldset>
<legend>Points</legend>
<div class="editor-label">
Quarter
</div>
<div class="editor-field">
#Html.DropDownList("VBQuarter")
</div>
<div class="editor-label">
User
</div>
<div class="editor-field">
#Html.DropDownList("VBEEID")
</div>
<div class="editor-label">
Programs
</div>
<div class="editor-field">
#Html.DropDownList("FK_Programs", String.Empty)
</div>
<div class="editor-label">
Points
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Points)
</div>
<div class="editor-label">
Entery Date
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.EntryDate, new {#Value = ViewBag.EntryDate, #readonly="readonly" })
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Your problem is in constructor of JoinClass. You should not initialize virtual navigation properties collection with new HashSet<T>. Entity framework use its own collection type - EntityCollection<T>. You should not initialize navigation property collections at all.
PS: It is good practice to use special viewmodels with views and pass data from viewmodels to entity models explicit.

Using one html.editorfor to fill in two model fields

Im trying to use only 1 html.editorfor to fill in two model field in each of my model.
I want the value of this editorfor to be also inserted to my Clientes0013.Client0013
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.Client00130012)
#Html.ValidationMessageFor(model => model.CanaClie0012.Client00130012)
</div>
and this one to be also inserted to Clientes0013.F1Pais00200013
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.F1Pais00200012)
#Html.ValidationMessageFor(model => model.CanaClie0012.F1Pais00200012)
</div>
Kindly show me what should be the right way of doing this.
My Table Model:
public partial class CanaClie0012
{
public string Client00130012 { get; set; }
public string F1Pais00200012 { get; set; }
public string F1Cana02530012 { get; set; }
public string Direcc0012 { get; set; }
public Nullable<System.DateTime> TmStmp0012 { get; set; }
}
public partial class Clientes0013
{
public string Client0013 { get; set; }
public string Nombre0013 { get; set; }
public string F1Pais00200013 { get; set; }
}
My Custom Model to combine the two table is:
public class ClientModel
{
public CanaClie0012 CanaClie0012 { get; set; }
public Clientes0013 Clientes0013 { get; set; }
}
My Controller:
[HttpPost]
public ActionResult ClientCreate(CanaClie0012 canaclie0012, Clientes0013 clientes0013)
{
ClientModel vm = new ClientModel();
if (ModelState.IsValid)
{
db.CanaClie0012.Add(canaclie0012);
db.Clientes0013.Add(clientes0013);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
My View:
#model MvcApplication1.Models.ClientModel
#{
ViewBag.Title = "ClientCreate";
}
<h2>ClientCreate</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>ClientModel</legend>
<div class="editor-label">
Client Name
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.Client00130012)
#Html.ValidationMessageFor(model => model.CanaClie0012.Client00130012)
</div>
<div class="editor-label">
Pais
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.F1Pais00200012)
#Html.ValidationMessageFor(model => model.CanaClie0012.F1Pais00200012)
</div>
<div class="editor-label">
Address
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.Direcc0012)
#Html.ValidationMessageFor(model => model.CanaClie0012.Direcc0012)
</div>
<div class="editor-label">
Contact Number
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Clientes0013.Nombre0013)
#Html.ValidationMessageFor(model => model.Clientes0013.Nombre0013)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Got it.. modified my controller action to this one.
[HttpPost]
public ActionResult ClientCreate(CanaClie0012 canaclie0012, Clientes0013 clientes0013)
{
ClientModel vm = new ClientModel();
if (ModelState.IsValid)
{
clientes0013.Client0013 = canaclie0012.Client00130012;
clientes0013.F1Pais00200013 = canaclie0012.F1Pais00200012;
db.CanaClie0012.Add(canaclie0012);
db.Clientes0013.Add(clientes0013);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}

MVC3 View doesn`t display empty form on validation passed

Very simple situation, here is my model:
public class Comment
{
[Required]
public string Name { get; set; }
[Required]
public string Text { get; set; }
}
Here is my controller:
public class CommentController : Controller
{
//
// GET: /Comment/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Comment/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
Comment new_comment = new Comment();
if (TryUpdateModel(new_comment))
{
return View(new Comment()); //problem is there
}
else
{
return View(new_comment);
}
}
}
And here is my standart genered strongly-typed View:
#model test.Models.Comment
#{
ViewBag.Title = "Create";
}
<h2>Create</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>Comment</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Text)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Text)
#Html.ValidationMessageFor(model => model.Text)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Problem is: when I enter valid data, TryUpdateModel() returns true, and
return View(new Comment());
should display empty form, because new empty instance of Comment is passed, but it still displays form with values entered earlier.
Please somebody tell me why. How to make it display empty form again?
Clear the modelstate:
if (TryUpdateModel(new_comment))
{
ModelState.Clear();
return View(new Comment()); //no more problem here
}
All HTML helpers first look at the ModelState when rendering their values and only after that in the model.
Or even better and more properly use the Redirect-After-Post pattern (i.e. redirect after a successful POST):
if (TryUpdateModel(new_comment))
{
return RedirectToAction("Create");
}

DateTime required in ModelState, however never set to be

I have a DateTime field in my form. For whatever reason, everytime I submit the form ModelState comes back as invalid and a message that my date time field (called PostDate) is required, even though in the view model I don't have the required attribute set.
Does anyone know why this would be happening as I'm going around in circles trying to figure it out.
Here is the view model
public class BlogViewModel
{
[Required]
public string Title { get; set; }
[Required]
public string Content { get; set; }
public bool Published { get; set; }
public DateTime PostDate { get; set; }
}
Here is the controller actions
public ActionResult Create()
{
return View();
}
//
// POST: /Admin/Blog/Create
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(BlogViewModel model)
{
if(ModelState.IsValid)
{
model.Content = HtmlSanitizer.SanitizeHtml(model.Content);
Services.BlogService.CreateBlogPost(model.Title, model.Content, User.Identity.Name);
return RedirectToAction("Index");
}
return View(model);
}
Here is the View
#using Payntbrush.Infrastructure.Mvc.Extensions
#model Payntbrush.Presentation.Demo.MVC3.Areas.Admin.Models.BlogViewModel
#Html.Resource(Html.ScriptTag("Areas/Admin/js/plugins/wysiwyg/jquery.wysiwyg.js"), ResourceType.Js)
<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((string)ViewBag.Action, "Blog", FormMethod.Post, new { Id = "BlogEditor" }))
{
#Html.ValidationSummary(true)
<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.Content)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Content, new { #class = "wysiwyg blog-editor" })
#Html.ValidationMessageFor(model => model.Content)
</div>
<div class="editor-label">
Time of post (Only set this if you want to make a post appear to have been published at a different date.)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.PostDate, new{#class="datetimepicker"})
#Html.ValidationMessageFor(model => model.PostDate)
</div>
<div class="editor-label">
Published (Check to make this post live on the site)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.Published)
#Html.ValidationMessageFor(model => model.Published)
</div>
<p>
<input class="large awesome" type="submit" value="Create" />
#Html.ActionLink("Cancel", "Index", "Blog", null, new { #class = "large awesome cancel-button" })
</p>
}
<div>
</div>
If you leave the corresponding field empty your model will be invalid because DateTime is a value type. You should use a nullable DateTime if you want to allow empty values:
public DateTime? PostDate { get; set; }

Resources