MVC-5 Razor Validation Errors showing on page load - asp.net-mvc

I have an insert page when I go to the insert page all the validation field is being shown,
[Required(ErrorMessage ="Please Enter Name")]
public string ccname { get; set; }
This is my class where I declared string ccname with required validation message
ENTER NAME
and it supposed to appear when user clicks on insert without entering data in ccname
but validatation message is being shown on the page load
#Html.TextBoxFor(model => model.ccname, new { #class = "textboxstyle" })
#Html.ValidationMessageFor(model => model.ccname)
I tried few things but nothing works,
here is an example
in my controller I added ModelState.clear();
public ActionResult insert()
{
ModelState.Clear();
return View();
}
and in my view I changed the code from
#Html.TextBoxFor(model => model.ccname, new { #class = "textboxstyle" })
#Html.ValidationMessageFor(model => model.ccname)
to
#Html.TextBoxFor(model => model.ccname, new { #class = "textboxstyle" })
#Html.ValidationMessageFor(model => model.ccname,"",new {#style= ".validation-summary-valid { display:none; }" })
but neither of these works
what should I do now?

Example:
Model:
public class MyModel
{
[Required(ErrorMessage ="Please Enter Name")]
public string ccname { get; set; }
}
Controller:
public class HomeController:Controller
{
[HttpGet]
ActionResult Insert()
{
var model =new MyModel();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
ActionResult Insert(MyModel model)
{
if(ModelState.IsValid)
{
//Do something
return View();
}
return View(model);
}
}
View
Insert.cshtml
#model MyModel
#using (Html.BeginForm("Insert", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.TextBoxFor(model => model.ccname, new { #class = "textboxstyle" })
#Html.ValidationMessageFor(model => model.ccname)
<input type="submit" value="Insert" class="btn btn-primary" />
}
#Scripts.Render("~/bundles/jqueryval")

Related

Stay on same page if form is not valid

public ActionResult Add(Models.ContactModel contact)
{
if (ModelState.IsValid)
{
DAL.Contact mappedContact = Mapper.Map<Models.ContactModel, DAL.Contact>(contact);
repository.AddContact(mappedContact);
return RedirectToAction("Index");
}
else
/* What to return here */
}
This is the controller for adding contact to the database. I am validating the form using data annotations if the form is valid i am redirecting it to the index page. If it is not valid it should stay on the same page showing error message. what to write in else part. can any one suggest me.There is no view for Add Controller.
<div>
<label>Name</label>
#Html.ValidationMessageFor(model => model.Name, null, new { #class = "error-message"})
#Html.TextBoxFor(model => model.Name, new { #class = "long-box" })
</div>
<div>
<label>Email</label>
#Html.ValidationMessageFor(model => model.Email, null, new { #class = "error-message" })
#Html.TextBoxFor(model => model.Email, new { #class = "long-box" })
</div>
<div class="mob-land-container">
<label>Mobile</label>
#Html.ValidationMessageFor(model => model.MobileNumber, null, new { #class = "error-message" }) <br>
#Html.TextBoxFor(model => model.MobileNumber, new { #class = "short-box" })
</div>
<div class="mob-land-container" id="landline-container">
<label>Landline</label>
#Html.ValidationMessageFor(model => model.LandlineNumber, null, new { #class = "error-message" })<br>
#Html.TextBoxFor(model => model.LandlineNumber, new { #class = "short-box" })
</div>
<div>
<label>Website</label>
#Html.ValidationMessageFor(model => model.Website, null, new { #class = "error-message" })
#Html.TextBoxFor(model => model.Website, new { #class = "long-box" })
</div>
<div>
<label>Address</label>
#Html.ValidationMessageFor(model => model.Address, null, new { #class = "error-message" })
#Html.TextAreaFor(model => model.Address, new { #class = "address-box" })
</div>
</div>
<div class="button-container">
<input type="button" id="cancel" value="Cancel" onclick="location.href='#Url.Action("Index", "Contact")'" />
<input type="submit" id="add" value="Add" onclick="location.href='#Url.Action("Add", "Contact")'" />
</div>
This is the form where i am getting data to controller.
public class ContactModel
{
public int Id { get; set; }
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Required(ErrorMessage = "Mobile Number is required")]
public string MobileNumber { get; set; }
[Required(ErrorMessage = "Landline Number is required")]
public string LandlineNumber { get; set; }
[Required(ErrorMessage = "Website is required")]
public string Website { get; set; }
[Required(ErrorMessage = "Address is required")]
public string Address { get; set; }
}
This is the model class.
Thanks in advance.
I like to flip the login in situations like this. If the model isn't valid just return it back to the view. the model binder on the POST will take care of the validations and once you send the model back to the view, you will see the individual validations on the screen.
If you have any dropdown, you will need to re-populate them before sending sending the model back.
public ContactController : Controller
{
[HttpGet]
public ActionResult Add()
{
return View(new Models.ContactModel());
}
[HttpPost]
public ActionResult Add(Models.ContactModel contact)
{
if (!ModelState.IsValid)
{
return View(contact);
}
DAL.Contact mappedContact = Mapper.Map<Models.ContactModel, DAL.Contact>(contact);
repository.AddContact(mappedContact);
return RedirectToAction("Index");
}
}
The GET action returns the empty form.
The POST action posts the model to the server.
Your view model should be named Add.cshtml to that mvc can automatically pick it up.
And change your view buttons
<div class="button-container">
#Html.ActionLink("Cancel", "Index", "Contact")
<input type="submit" value="Save" />
</div>
Style the Cancel link to look like a button
Your submit will automatically submit to the Add POST method.
The model state check returns the model back to the view with the validation information in it so that you can correct the form.

MVC model conflict using partial class and Validate

I have a page containing a form and a partial view (containing a form too).
both model have 1 (or more) properties with the same name. when I validate the first form, the value and validation message is duplicate on the second form.
I create a little sample with dummy entities.
person.cs
public partial class Person : IValidatableObject
{
[Required(ErrorMessage = "name required")]
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (Name == "admin") //just example
{
results.Add(new ValidationResult("You cant be admin.", new[] { "Title", "Name" }));
}
return results;
}
}
Person/Index.cshtml
#model Person
#{
ViewBag.Title = "Person";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("Index", "Person", FormMethod.Post, new { id = "CreatePersonForm" }))
{
#Html.AntiForgeryToken()
#Html.DisplayNameFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
<input type="submit" value="Save" class="btn btn-default" />
}
#Html.Partial("~/Views/Dog/Index.cshtml", new Dog())
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
PersonController.cs
public class PersonController : Controller
{
// GET: Person
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([Bind(Include = "Name")] Person person)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View(person);
}
}
I made a partial view practically the same.
Dog.cs
public partial class Dog : IValidatableObject
{
[Required(ErrorMessage = "name required")]
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (Name == "admin") //just example
{
results.Add(new ValidationResult("You cant be admin.", new[] { "Title", "Name" }));
}
return results;
}
}
Dog/Index.cshtml
#model Dog
#{
ViewBag.Title = "Dog Page";
}
#using (Html.BeginForm("Index", "Dog", FormMethod.Post, new { id = "CreateDogForm" }))
{
#Html.AntiForgeryToken()
#Html.DisplayNameFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
<input type="submit" value="Save" class="btn btn-default" />
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
DogController.cs
public class DogController : Controller
{
// GET: Dog
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([Bind(Include = "Name")] Dog dog)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View(dog);
}
}
if you start /Person/Index, if you write admin in the first textbox (person form), after posting (save) the second form (dog form) have the same text and validation than the first form.
The #Html.EditorFor by default uses the property name as the id and name of the generated HTML, and the validation uses these values to set the error messages! You can pass a value to overwrite that default behavior in your partial view as following:
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger", #data_valmsg_for="partial_name" })
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control", #id="partial_name" } })

MVC MultipleModel DropdownlistFor SaveChanges()

HI i Have a MultipleModel View with CompanyName and EmployeeRange. CompanyName contains names of companies with a Relationship link to EmployeeRange (int) Field.
The Employee Range is basically
0-9
10-19
20-49
I can create and SaveChanges for a new Company Name Field.
Please help With Saving Selected value from the EmployeeRange DropDownListFor to DB.
Here is the Code
//MultipleModel.cs
public partial class MultipleModel
{
public MultipleModel()
{
CompanyEntities = new company();
EmployeeEntities = new Employee();
}
public company CompanyEntities { get; set; }
public Employee EmployeeEntities { get; set; }
}
//CompanyController.cs
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RegisterCompany(MultipleModel model)
{
if (ModelState.IsValid)
{
//GET VARIBALE FROM DB
var addComanyName = db.companies.Add(model.CompanyEntities);
//GET VARIABLLE
addComanyName.COMPANY_NAME = model.CompanyEntities.COMPANY_NAME;
//ADD VARIBALE TO DB
db.companies.Add(addComanyName);
db.SaveChanges();
return RedirectToAction("index");
}
return View();
}
//RegisterCompany.cshtml
#model EISystem.Models.MultipleModel
#Html.DropDownListFor(m => m.CompanyEntities, new SelectList(ViewBag.products, "Employees_Range_ID", "Employees_Range"), "Select Number of Employees")
?? How Do i view the DropDownListFor so that selected Value can be POST to Controller and later be saved to DB?
You should use another class which is ViewModel for your MultipleModel class.
Like:
public class MultipleModelViewModel
{
public int SelectedProductId { get; set; }
public List<Products> ProductList{ get; set; }
public string Name { get; set; }
}
In a View
#model MultipleModelViewModel
#using (Html.BeginForm("RegisterCompany", "Company", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(model => model.SelectedProductId , htmlAttributes: new { #class = "form-control" })
#Html.DropDownListFor(model => model.SelectedProductId, new SelectList(Model.ProductList, "Id", "Name"), "Select Product", new { #class = "form-control " })
</div>
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "form-control " })
#Html.TextBoxFor(model => model.Name, new { #class = "form-control" })
</div>
<button type="Submit" class="btn btn-success " id="Save-btn">
Save
</button>
}
Controller:
//Get
public ActionResult RegisterCompany()
{
var model = new MultipleModelViewModel (){
Name = model.Name,
Products = db.Products.Select(x=>new {Id=x.Id, Name=x.Name).ToList()
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RegisterCompany(MultipleModelViewModel model)
{
if (ModelState.IsValid)
{
var company = new Company(){
Name = model.Name,
Product = db.Products.Find(model.SelectedProductId)
};
db.companies.Add(company);
db.SaveChanges();
return RedirectToAction("index");
}
return View();
}

MVC model validation

So, im currently building an application that needs the user model validating, and if the incorrect properties are filled in to the user it will tell them.
I have the data annotations set up, but im not sure how i relay the error message back to the user?
I have this set up so far on my model and view.
Model
public class DatabaseModel
{
[Required(ErrorMessage = ("A first name is required"))]
public string FirstName { get; set; }
[Required(ErrorMessage = ("A last name is required"))]
public string LastName { get; set; }
[Required(ErrorMessage = ("A valid role is required"))]
public string Role { get; set; }
// TODO - Validate rank to only b 1 - 10
//
[Range(1,10, ErrorMessage = ("A rank between 1 and 10 is required"))]
public int Rank { get; set; }
}
And View
#model RoleCreatorAndEditor.Models.DatabaseModel
#{
ViewData["Title"] = "Index";
}
<h2>User Information</h2>
<p>This is your user information!</p>
#using (Html.BeginForm("Index", "Home", FormMethod.Post)) {
#Html.Label("First Name")
<br>
#Html.TextBoxFor(m => m.FirstName)
<br>
#Html.Label("Last Name")
<br>
#Html.TextBoxFor(m=>m.LastName)
<br>
#Html.Label("Role")
<br>
#Html.TextBoxFor(m => m.Role)
<br>
#Html.Label("Rank")
<br>
#Html.TextBoxFor(m => m.Rank)
<br><br>
<input type="submit" value="Save">
}
My Controller
public class HomeController : Controller
{
// GET: Home
[HttpGet]
public ActionResult Index()
{
DatabaseModel model = new DatabaseModel();
return View(model);
}
[HttpPost]
public ActionResult Index(DatabaseModel model)
{
if (ModelState.IsValid)
{
ListToDatatable convert = new ListToDatatable();
DataTable user = convert.Convert(model);
DatabaseRepository dbRepo = new DatabaseRepository();
dbRepo.Upload(user);
}
return View();
}
}
I believe the model needs to be passed back to the view in order to display the error message, and although i have read through the documentation on asp.net i cannot understand how they just add the error message and the form knows how to display the errors to the user.
I am extremely confused.
You need to use ModelState.IsValid in your Controller and also #Html.ValidationMessageFor(model => model.FirstName) in your view:
public ActionResult Index(ViewModel _Model)
{
// Checking whether the Form posted is valid one.
if(ModelState.IsValid)
{
// your model is valid here.
// perform any actions you need to, like database actions,
// and/or redirecting to other controllers and actions.
}
else
{
// redirect to same action
return View(_Model);
}
}
For your example:
#model RoleCreatorAndEditor.Models.DatabaseModel
#{
ViewData["Title"] = "Index";
}
<h2>User Information</h2>
<p>This is your user information!</p>
#using (Html.BeginForm("Index", "Home", FormMethod.Post)) {
#Html.LabelFor(m=>m.FirstName)
<br>
#Html.TextBoxFor(m => m.FirstName)
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
<br>
#Html.LabelFor(m=>m.LastName)
<br>
#Html.TextBoxFor(m=>m.LastName)
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
. . .
<input type="submit" value="Save">
}
Controller:
[HttpPost]
public ActionResult Index(DatabaseModel model)
{
if (ModelState.IsValid)
{
ListToDatatable convert = new ListToDatatable();
DataTable user = convert.Convert(model);
DatabaseRepository dbRepo = new DatabaseRepository();
dbRepo.Upload(user);
}
return View(model);
}

Losing form values after validation

Using a ViewModel for validation:
public class CCvm
{
[Required(ErrorMessage = "Please enter your Name")]
public string cardHolderName { get; set; }
}
My controller calls a task on post:
public async Task<ActionResult> Pay(FormCollection form, CCvm model)
{
if (!ModelState.IsValid)
{
return View(model);
}
}
And the View:
#model GCwholesale.Models.CCvm
#{
Layout = "~/Views/Shared/_HomeSubPageLayout.cshtml";
ViewBag.Title = "Secure Checkout";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="Payment">
<label>Name on Card: </label>
#Html.EditorFor(model => model.cardHolderName, new { htmlAttributes = new { #placeholder = "Cardholder Name Please", #Value = ViewBag.Name } })<br />
#Html.ValidationMessageFor(model => model.cardHolderName)
<button class="submitCheckout">SUBMIT NOW</button>
</div>
}
But when validation fails the data in the form goes away.
Thanks for taking a look.
You do not need to set #Value = ViewBag.Name inside EditorFor.
#Html.EditorFor(model => model.cardHolderName,
new { htmlAttributes = new { #placeholder = "Cardholder Name Please" } })
Besides, you do not need FormCollection as a parameter because you already have CCvm Model.
public async Task<ActionResult> Pay(CCvm model){
{
//...
}
#Value = ViewBag.Name
You're not setting the ViewBag.Name, so it wouldn't have a value and would result in a blank input. Remove that and let the HtmlHelper set it based off the value in the posted model.

Resources