I'm new to MVC3. I have problem in custom validation, for example
In my BasicInfoViewModel.cs,
[Required]
[Display(Name = "State", ResourceType = typeof(Resources.Global))]
public string State { get; set; }
[Display(Name = "City", ResourceType = typeof(Resources.Global))]
public string City { get; set; }
In my BasicDetailsView.cshtml,
<label>
<span class="td">#Application.Resources.Global.State</span>
#Html.DropDownListFor(m => m.State, (List<SelectListItem>)ViewData["State"])
</label>
<label>
<span class="td">#Application.Resources.Global.City</span>
#Html.DropDownListFor(m => m.City, (List<SelectListItem>)ViewData["City"])
</label>
If the state property returns true, then only "City" is required. If not, City is not required, then the textbox should be diabled.
I'm not using EditorFor, using DropDownListFor because i'm using plain html. Can anyone help me to solve this issue?
Thanks...
MVC Foolproof is a set of validation data annotations that extend the existing ones and provide additional functionality. For example the [RequiredIfNotEmpty] attribute from this package is quite suitable for your scenario as it allows for conditional validation.
[Display(Name = "State", ResourceType = typeof(Resources.Global))]
public string State { get; set; }
[RequiredIfNotEmpty("State")]
[Display(Name = "City", ResourceType = typeof(Resources.Global))]
public string City { get; set; }
Now the State property is optional. But if it has some value then the City property is required.
You might want to look at RequiredIfAttribute. To make your city dropdownlist disabled - use jquery. For checking if data is valid you have js method $("selector").valid() which returns 0 or 1 and also shows validation message for specified field
Related
I am using ASP.NET Core v2,
See picture showing SQL data type and the code in the model
I do not want to display decimal if there are no decimals
The following html is used to show the input on web page
<input tabindex=#ordTab asp-for="#Model.OrderLineList[i].NoInvoAb" />
below is SQL
below is the model
I have tried many different display formats/dataformatstring but it does not seem to matter what I use, like the formatting does not seem to apply at all
[Required]
[DisplayFormat(DataFormatString = "{0:0}")]
[Display(Name = "Ordered")]
public decimal NoInvoAb { get; set; }
This is my result which is wrong, if the value is 2, it should display 2 and not 2,00
what am I doing wrong
DisplayFormat by default is for display. Here, it looks like the value is in an input. If you want the format apply there as well, then you need to add ApplyFormatInEditMore = true to your DisplayFormat attribute.
[Required]
[DisplayFormat(DataFormatString = "{0:0}", ApplyFormatInEditMode = true)]
[Display(Name = "Ordered")]
public decimal NoInvoAb { get; set; }
I have a model for customer
public class Customer
{
public virtual int CustomerID { get; set; }
[Required]
public virtual string CustomerName { get; set; }
[Required]
public virtual string Title { get; set; }
[Required]
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
// Cont..
}
When I post the customer creation form to public ActionResult Create(Customer customer) which is an action in my CustomerController, it produce error against ModelState. For example... if my code is like below..
[HttpPost]
public ActionResult Create(Customer customer)
{
customer.Title = "Mr"; // This is what I set for ensuring the field has value
if (ModelState.IsValid)
{
// Code to save customer entity
}
// else..
}
In my MVC view it show the error in Customer Title
for instance, if I remove the if (ModelState.IsValid) portion from the code above, the customer entity is saved fine and I can see the record in database.
What might be the issue here?
EDIT :
passing Customer Titles as IEnumerable<SelectListItem>
ViewData["CustomerTitles"] = GetCustomerTitles();
Code in view
div class="editor-field">
<%: Html.DropDownList("CustomerTitles")%>
<br /><%: Html.ValidationMessageFor(model => model.Title) %>
</div>
Try this:
<%: Html.DropDownList("Title", new SelectList(ViewData["CustomerTitles"]), Customer.Title.ToString()) %>
This should hopefully pass the title in as a string, which is what your Model is asking for.
Thanks, I learnt the answer for this question from the reply of #Richard A.
I did some modification to my code and it works fine.
I post it below, so might help some one.
ViewData from Controller
ViewData["Title"] = GetCustomerTitles(customer.Title);
View
<div class="editor-field">
<%: Html.DropDownList("Title") %>
<br /><%: Html.ValidationMessageFor(model => model.Title) %>
</div>
The Idea is.. in Entity, the field name is "Title". After the form is posted, compiler check for a HTML element having the name "Title" and assign its value. If it is not present, it set the value of ModelState to false.
I have a ‘Create’ page in my MVC3 application that has 4 input fields that are all required. I also have an ‘Edit’ page in which 3 of these 4 fields can be edited. I do not want to display the 4th field and want to maintain it at its initial value (the field is the date that the entry was created ).
I mark the 4th field as [Required] in the model then this causes the model to be declared as invalid in post action method of the Edit field. If I omit the [Required] annotation then someone can create a user with a null value for this 4th field.
How can I get around this problem?
Model Code:
[Required]
[DisplayName("User Name")]
public string UserName { get; set; }
[Required]
public string Role { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayName("Insert Date")]
public DateTime? InsertDate { get; set; }
[Required]
[DisplayName("Active")]
public bool ActiveInd { get; set; }
Controller Code:
public ActionResult Edit(int id, ZUserRoleModel mod)
{
if (ModelState.IsValid)
{
// code removed
return RedirectToAction("Index");
}
return View(mod);
}
You can make that field as hidden in edit mode.
#Html.HiddenFor(x => x.EntryDate)
Not sure if you still need an answer for this, but what you need to do in order for the
#Html.HiddenFor(x => x.EntryDate )
to work, is pass an existing model into view. So let's assume that your action for getting the user data looks like this. ( You did not supply it, so I am not sure if this is right )
Public ActionResult GetUser(int UserID)
{
ZUserRoleModel model = new ZUserRoleModel(UserID);
// Maybe this could go to your database and gather user
// It would populate the correct data into a model object
return View("Edit", model);
}
With combination of the hidden field, your view will be populated with the existing user information, and the hidden field will be populated with data, and it will be passed to your edit action.
NOTE: I wrote this without any kind of testing, but it should still work, or at the very least, I hope it points you in the right direction if you still need assistance.
You can use fluentvalidation: http://fluentvalidation.codeplex.com/
Have a rule that's something like
RuleFor(user => user.field4).NotEmpty().When(ViewContext.Controller.ValueProvider.GetValue("action").RawValue <> "edit")
Similar to this post IEnumerable model property in an ASP.NET MVC 3 Editor Template, I have
Model
public class Student
{
public int StudentId { get; set; }
public string StudentName{ get; set; }
//FYI..Its virtual because of EF relationship
public virtual ICollection<Class> Classes{ get; set; }
}
public class Class
{
public int ClassId { get; set; }
public string ClassName{ get; set; }
}
View - EditStudent
#model Student
#Html.TextBoxFor(m => m.StudentName)
//I get the error for following..see below
#Html.EditorFor(m => m.Classes);
Student/EditorTemplates/Class
#model Class
<div>
#*checkbox here*#
#Html.LabelFor(x => x.ClassName)
</div>
Controller
public ActionResult EditStudent(int id)
{
ViewBag.Classes = repository.GetClasses();
Student student = repository.GetStudent(id);
return View("EditStudent", student);
}
Error in View on statement #Html.EditorFor(m => m.Classes); is..
The model item passes into the dictionary is of type
'System.Collections.Generic.HashSet`1[Class]', but this dictionary
required a model item of type 'Class'.
Basically, what I am trying to achieve is to display the list of all classes available with a checkbox next to it ( I have not reached to that part of code yet). Then check all classes to a student is enrolled and allow to change the selections.
How do I display the list of checkboxes with the given Model.
Should I bind my EditorTemplate with ViewBag.Classes (How?) or ?
I need to get selected checkbox values in Post ActionMethod as well.
I read some posts those suggest to create CheckBoxListHelper, but it should be possible to do with EditorTemplate as I need to display a simple list.
Please suggest. Thanks.
Okay, I figured it out. Thanks to very precise post here
How to provide an EditorTemplate for IEnumerable<MyModel>?
First, I renamed the EditorTemplate to StudentClass - not sure if this has anything to do with binding or not, but I did.
Second, modified EditorTemplate to bind with IEnumerable
#model IEnumerable<Class>
var checked = "";
#foreach (Class class in ViewBag.Classes)
{
if (Model != null)
{
Class class = Model.FirstOrDefault(c => c.ClassId.Equals(class.ClassId));
if (class != null)
{
checked = "checked=checked";
}
}
<input type="checkbox" name="Classes" value="#class.ClassId" #checked />
#class.ClassName
}
And I call the template with name
#Html.EditorFor(m => m.Classes, "StudentClass");
Now in controller's Post method I can get the array of Classes (name of checkboxes).
I'm getting odd behavior with my validation in my view.
My model has this property.
[Display(Name = "Overflow Capacity")]
[RegularExpression(#"[-+]?[0-9]*\.?[0-9]?[0-9]", ErrorMessage = "Number required.")]
[Range(0,9999.99,ErrorMessage = "Value must be between 0 - 9,999.99")]
public decimal OverFlowCapacity { get; set; }
My view has this:
<tr>
<td>#Html.LabelFor(m=> m.OverFlowCapacity)</td>
<td>#Html.EditorFor(m=>m.OverFlowCapacity)</td>
<td> #Html.ValidationMessageFor(model => model.OverFlowCapacity)</td>
</tr>
If I enter a value like 'ABC', I get the validation message 'Number required'
If I enter a value of 999999, I get the validation message 'Value must be between 0 - 9,999.99'
Both of those messages are received when I tab off the text box as expected.
When I leave the text box value empty and tab off, I get no errors, as expected.
However, when I submit, I get a validation message 'The Overflow Capacity field is required.'
I don't know where this is coming from. I've tried removing all validation attributes from the model, and still get the 'required' message. I'm at a loss.
Here are the scripts I've referenced.
I have other issues with mvcfoolproof that I may post later. I'm wondering if this isn't somehow responsible for my problems.
What's happening to you now is the post validation is kicking in after the form has been submitted and determining that the decimal value cannot be null. Right now you are using a decimal type which is non-nullable. If you want this behavior and you want to see the validation before you submit the form then add the [Required] attribute to the property. However if you don't want this functionality and it can possibly be null, then change your type from decimal to decimal? or Nullable<decimal>.
Don't allow nulls and have the pre-submit validation:
[Display(Name = "Overflow Capacity")]
[RegularExpression(#"[-+]?[0-9]*\.?[0-9]?[0-9]", ErrorMessage = "Number required.")]
[Range(0,9999.99,ErrorMessage = "Value must be between 0 - 9,999.99")]
[Required]
public decimal OverFlowCapacity { get; set; }
Allow nulls and get rid of post-submit validation error:
[Display(Name = "Overflow Capacity")]
[RegularExpression(#"[-+]?[0-9]*\.?[0-9]?[0-9]", ErrorMessage = "Number required.")]
[Range(0,9999.99,ErrorMessage = "Value must be between 0 - 9,999.99")]
public decimal? OverFlowCapacity { get; set; }
Since you're not marking your decimal type as nullable, MVC doesn't know what to do with the empty field you're posting back. Try this if you want to allow nulls/empty fields:
public decimal? OverFlowCapacity { get; set; }
and try this if you want it to have a pre-submit validation message requiring the field to be filled in:
[Required]
public decimal OverFlowCapacity { get; set; }
Answers above explain Required error message quite well so i will just focus on second error message. i.e if you put 'abc' jquery tells you "Number Required". How does jquery know that this input should only accept number fields. The answer is; through unobtrusive attributes that are generated with form fields. If you inspect input field you will find something like
<input name="OverFlowCapacity" id="OverFlowCapacity" data-val-number="Number Required"..../>
so to override this default validation message you have to decorate your model with the attribute that does the exact same thing (number validation) and their you can override the validation message
[Numeric(ErrorMessage="override message")]
[Required(ErrorMessage="override Required message")]
public decimal OverFlowCapacity{get;set;}
I doubt Numeric attribute is present in DataAnnotation or mvc framework. you have to check into that. There are some useful attributes discussed and available here