ASP.NET MVC Razor - All form fields are required? - asp.net-mvc

I have a form that is generated by ASP.NET.
I have some required fields, and I am using the [Required] dataAnnotation for that.
However, the elements that don't have the [Required] DataAnnotation are also required according to my webpage. These are not required at all yet I cannot submit the form if they are empty.
I used scaffolding to make the pages, jquery validator is used (by default) for the validation.
Model class (some fields have been omitted for clarity)
public class Room
{
[Key]
public int ID { get; set; }
[Required(ErrorMessage = "Please enter the minimum (default) price for this room.")]
[DataType(DataType.Currency)]
[Display(Name = "Minimum price")]
public decimal MinPrice { get; set; }
[Display(Name = "Alternative price")]
[DataType(DataType.Currency)]
public decimal AltPrice { get; set; }
}
The code that creates the form fields in de .cshtml file:
<div class="form-group">
#Html.LabelFor(model => model.MinPrice, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MinPrice)
#Html.ValidationMessageFor(model => model.MinPrice)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AltPrice, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.AltPrice)
#Html.ValidationMessageFor(model => model.AltPrice)
</div>
</div>
The required field correctly displays the error message as defined (thus it reads the annotations).
The non required field displays a generic error message instead ("The Alternative price field is required.").
I've searched quite a lot, but everywhere it says that if the [Required] DataAnnotation is not there, it won't be required in the form.

Make the non-required fields nullable.

I was having the same problem. I had to go into my model and put ? marks in the int fields to make them null. The fields that were set as string were fine it was just the int fields that were causing the issue.

Related

mvc data annotation validator for datetime always shows required

when I submit my form, Termination date field shows "Termination Date field is required" even though I haven't defined it as required anywhere.
my model is defined as:
[Display(Name = "Termination Date")]
public DateTime TerminationDate { get; set; }
razor code is:
<div class="col-md-6 form-group">
#Html.LabelFor(model => model.Posting.TerminationDate)
#Html.TextBoxFor(model => model.Posting.TerminationDate, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Posting.TerminationDate)
</div>
I do not want any type of validation on this field. How can I do that?
Make the property nullable
DateTime? or Nullable<DateTime>
Or reconfigure the convention
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

MVC 5 scaffolding not emitting bootstrap classes for basic EF derived data

First off, I'm a newcomer to MVC and ASP.NET so apologies if I'm missing something simple.
I'm working on a code first MVC 5 application, for the sake of brevity lets say I have two Models defined like this:
public class Platform
{
[Key]
public int Id { get; set; }
[Required(ErrorMessage = "You must select a manufacturer")]
[DisplayName("Manufacturer")]
public int ManufacturerId { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
[Required(ErrorMessage="You must enter a name for the platform")]
[StringLength(50, ErrorMessage="Reduce length to 50 characters or less")]
public string Name { get; set; }
}
and
public class Manufacturer
{
[Key]
public int Id { get; set; }
[Required(ErrorMessage="You must enter a name for the manufacturer")]
[StringLength(50, ErrorMessage="Reduce length to 50 characters or less")]
public string Name { get; set; }
public virtual ICollection<Platform> Platforms { get; set; }
}
When creating 'MVC 5 Controller with views, using Entity Framework' scaffolding for these models all the CRUD actions are working correctly. The form elements on the other hand are unformatted, missing the form-control class that Bootstrap wants.
I can work around this per type by adding an EditorTemplate with something like #Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { #class = "form-control" }) in it, but surely the scaffolding for a Bootstrap MVC 5 project should be emitting valid code already? Looking at various MVC 5 tutorials they seem to be working correctly with proper styling, so I'm left somewhat confused as to what I'm doing wrong.
For reference, the output in the Create.cshtml file for each model (clipped to the important form elements for brevity) is:
<div class="form-group">
#Html.LabelFor(model => model.ManufacturerId, "ManufacturerId", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ManufacturerId", String.Empty)
#Html.ValidationMessageFor(model => model.ManufacturerId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
and
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
Why is the ManufacturerId being specified as the label text for the drop down when a DisplayName is set in the model?
Why is the drop down using DropDownList() instead of the strongly typed DropDownListFor()?
Thank you in advance.
It looks like MVC 5.1 will have a workaround for the form-control problem with Bootstrap 3, as stated here. It will be possible to pass styles for EditorFor.
Sounds like you did what I did - upgrade Bootstrap 2.x to 3.0 or 3.0.1. The Microsoft project templates are based on Bootstrap 2.x not 3.x. You can read about others bumping into on
GitHub.
I also got a reply from Rick Anderson of Microsoft who wrote several of the Tutorials on www.asp.net and he confirmed this...
Great catch. Actually, some of the images in my tutorial are from Beta and RC that are using bootstrap v2, not V3, so our images will differ. Look at the views for your account controller to see "form-control". You can download my complete project and compare with your project.
Regarding your other question, I ran into the same issue and think it may be a bug. Certain annotations appear to get ignored. Try adding a [ForeignKey()] annotation to Platform.ManufacturerId and see if it affects the field label.

Disable validation on a #Html.TextBox in MVC

I have a form in which I want to disable the required validation on one of the #Html.TextBox elements. The front end is as follows:
#model Models.NewUser
#using (Html.BeginForm("Register", "Account"))
{
<div class="field">
<span class="textOverField absolute em1-2" style="top:6px;left:4px;">Key</span>
#Html.TextBox("SchoolGroupKey", "", new { #class = "textField" })
</div>
<div class="field">
<span class="textOverField absolute em1-2" style="top:6px;left:4px;">Name</span>
#Html.TextBox("Names", "", new { #class = "textField" }) <div class="absolute validationMessage">#Html.ValidationMessageFor(u => u.Names)</div>
</div>
<div class="field">
<span class="textOverField absolute em1-2" style="top:6px;left:4px;">Last Name</span>
#Html.TextBox("LastNames", "", new { #class = "textField" }) <div class="absolute validationMessage">#Html.ValidationMessageFor(u => u.LastNames)</div>
</div>
<div class="em0-9" style="margin-bottom:20px;">
<input class="submitButton cursorHand" style="margin-top:10px;" type="submit" value="Registrarme" />
</div>
}
And the code for the model is as follows:
public class NewUser
{
[Required(ErrorMessage = "Name required")]
public string Names { get; set; }
[Required(ErrorMessage = "Last name required")]
public string LastNames { get; set; }
public System.Guid SchoolGroupKey { get; set; }
}
I'm guessing that the #Html.TextBox has a default validation even though I don't specify it. Is there someway to remove it?, I tried removing the html tags data-val-required and data-val, but still no results.
Thanks
Guid is a structure that behave as a simple type (just like int or DateTime). As such it is automaticly validated. If you want to make a workaround change your property type from Guid to nullable Guid?. Example:
public System.Guid? SchoolGroupKey { get; set; }
Of course you will have to change places when you use this property, to access the guid value throught Value property of nullable type.
If the mapping fails you will not get any validation errors then - just null value inside of your SchoolGroupKey property.

Unobtrusive javascript adding data to #Html.HiddenFor

I have a hidden field on a form that is created in Razor using the #Html.HiddenFor helper:
#Html.HiddenFor(model => model.BidID, new { id="bidItemID" })
My View model looks like this:
public class BidEditVM
{
[Display(Name = "Bid ID")]
public int BidID { get; set; }
[StringLength(51)]
[Display(Name = "Customer Name")]
public string CustomerName { get; set; }
[StringLength(75)]
[Display(Name = "Bid Name")]
public string BidName { get; set; }
[Display(Name = "Amount")]
public decimal Amount { get; set; }
[Display(Name = "Time")]
public DateTime BidTime { get; set; }
}
When the HTML is rendered, unobtrusive javascript adds it's stuff to the hidden input field even though it will never require validation:
<input id="bidItemID" type="hidden" value="5198" name="BidID" data-val-required="The Bid ID field is required." data-val-number="The field Bid ID must be a number." data-val="true">
What's odder is that the message and validation it adds aren't even part of the view model for this partial view. The view looks like this:
#model AuctionAdmin.Models.ViewModels.BidEditVM
#using (Ajax.BeginForm("UpdateBid", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "modalBidInfo" }))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.BidID, new { id="bidItemID" })
<fieldset>
<legend>Edit Bid</legend>
<div class="display-label">#Html.LabelFor(model => model.CustomerName)</div>
<div class="display-field">
#Html.DisplayFor(model => model.CustomerName)
</div>
<div class="display-label">#Html.LabelFor(model => model.BidName)</div>
<div class="display-field">
#Html.DisplayFor(model => model.BidName)
</div>
<div class="editor-label">#Html.LabelFor(model => model.Amount)</div>
<div class="editor-field">
#Html.EditorFor(model => model.Amount)
</div>
<div class="editor-label">#Html.LabelFor(model => model.BidTime)</div>
<div class="editor-field">
#Html.EditorFor(model => model.BidTime)
</div>
</fieldset>
}
Where is it getting this metadata from and how can I stop it?
It's marked as such since the type in the view model is an int.
It's adding the html due to this line:
#Html.HiddenFor(model => model.BidID, new { id="bidItemID" })
Why is it a problem that the extra attributes are present?
If it really is problematic, try changing the type of BidId to int? (a nullable int).

Using System.ComponentModel.DataAnnotations with Entity Framework 4.0

I'm working with MVC3, and using Entity Framework 4.0 Entities as my model. So far, everything works great as far as using it as a model (all the crud operations/page generations work out of the box). I'm wondering, though, how do you get the same robust labels and validation information as when you generate a model manually?
Here's an example of what I mean. This is a class generated by the sample MVC3 project:
public class LogOnModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
With the example above, you can specify what gets rendered in a label for the field (Display), and what type of field to use (Password). However, when I try to use the entity framework and push it to the view below, I see the automatically generated labels are just the field names, and not anything I want the user to see/have to read:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Person</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.MiddleName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MiddleName)
#Html.ValidationMessageFor(model => model.MiddleName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</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>}
My question is: How do I add these extra decorations to the entities that are generated using EF4? Is there something besides System.ComponentModel.DataAnnotations that I should be using? I know entities get regenerated and it's probably not a good idea to add this to entities' code directly, but for some reason I can't think of a better approach than manually entering the label text in the view (lame, there's no reason to have to do that, this is MVC!). I want to keep it so that the application is dynamic enough to be able to have the correct display information for my model come through and keep an MVC approach. How do I do it?
I haven't done this for ASP.NET MVC (only for Silverlight) but I believe the same principles would apply. You can create a "metadata buddy class" as below, because the types generated by EF should be partial, thus you can add a bit more to them (like the MetadataTypeAttribute) and then you create this sibling class that holds the metadata.
It's kind of ugly, but should work. It goes something like this (assuming the EF entity is named "Person"):
[MetadataType(typeof(PersonMetadata))]
public partial class Person {
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class PersonMetadata {
// Name the field the same as EF named the property - "FirstName" for example.
// Also, the type needs to match. Basically just redeclare it.
// Note that this is a field. I think it can be a property too, but fields definitely should work.
[Required]
[Display(Name = "First Name")]
public string FirstName;
}
Same as above but with all the details, and it works
And Here is the Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace Validate.Models
{
[MetadataType(typeof(PersonMetadata))]
public partial class Person
{
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class PersonMetadata
{
// Name the field the same as EF named the property - "FirstName" for example.
// Also, the type needs to match. Basically just redeclare it.
// Note that this is a field. I think it can be a property too, but fields definitely should work.
[Required]
[Display(Name = "Enter Your Name")]
public string FirstName;
}
}
Like Austin Lamb's answer, but instead, nesting the MetaData class within the entity class, thereby reducing the number of classes in your public namespace list, and eliminating the need to have a unique name for each metadata class.
using System.ComponentModel.DataAnnotations;
namespace Validate.Models
{
[MetadataType(typeof(MetaData))]
public partial class Person
{
public class MetaData
{
[Required]
[Display(Name = "Enter Your Name")]
public string FirstName;
//...
}
}
}

Resources