In MVC2 the validation I use for a drop down list works;
<tr>
<td align="right">
<%: Html.LabelFor(model => model.contract.ContractTypeId)%><span class="error">*</span>
</td>
<td>
<%: Html.DropDownListFor(model => model.contract.ContractTypeId, Model.contractTypesSelectList, "<--Select-->")%>
<%: Html.ValidationMessageFor(model => model.contract.ContractTypeId)%>
</td>
</tr>
and with data annotation;
[DisplayName("Contract Prefix")]
[UIHint("DropDownList")]
[Required(ErrorMessage = "You must select a Contract Prefix")]
public int ContractTypeId { get; set; }
If I try this in MVC3, it no longer works;
<tr>
<td align="right">
@Html.LabelFor(开发者_运维技巧model => model.contract.ContractTypeId)<span class="error">*</span>
</td>
<td>
@Html.DropDownListFor(model => model.contract.ContractTypeId, Model.contractTypesSelectList, "<--Select-->")
@Html.ValidationMessageFor(model => model.contract.ContractTypeId)
</td>
</tr>
data annotation;
[DisplayName("Contract Prefix")]
[UIHint("DropDownList")]
[Required(ErrorMessage = "You must select a Contract Prefix")]
public int ContractTypeId { get; set; }
What am I doing wrong?
EDIT
Actually what is happening is that when I click submit, the other fields are flagging up as invalid. When I correct them and click submit, then the drop downs flag up as invalid. So it kind of works, but should work all at the same time, rather than in this sequence.
My controller is; #region CREATE /******** * CREATE ***** */ [Authorize(Roles = "Inputter,Administrator")] public ViewResult Create() { return View(new ContractViewModel()); }
//
// POST: /Contract/Create
[Authorize(Roles = "Inputter,Administrator")]
[HttpPost]
public ActionResult Create(ContractViewModel contractViewModel)
{
if (ModelState.IsValid)
{
CapitaliseNames(ref contractViewModel);
int contractId = contractViewModel.contract.Add();
// Store the Addresses for Client and Contract Administrator on the database,
// and store the Ids of the new addresses on the Contract object.
contractViewModel.clientContact.ContractId = contractId;
contractViewModel.contractAdministratorContact.ContractId = contractId;
int clientContactId = contractViewModel.clientContact.Add();
int contractAdministratorContactId
= contractViewModel.contractAdministratorContact.Add();
contractViewModel.contract.Update(clientContactId, contractAdministratorContactId);
return RedirectToAction("List");
}
return View(new ContractViewModel());
}
private static void CapitaliseNames(ref ContractViewModel contractViewModel)
{
contractViewModel.clientContact.ContactName = contractViewModel.clientContact.ContactName.UppercaseFirst();
contractViewModel.clientContact.NameOfContact = contractViewModel.clientContact.NameOfContact.UppercaseFirst();
contractViewModel.contractAdministratorContact.ContactName = contractViewModel.contractAdministratorContact.ContactName.UppercaseFirst();
contractViewModel.contractAdministratorContact.NameOfContact = contractViewModel.contractAdministratorContact.NameOfContact.UppercaseFirst();
}
#endregion
My View is; @model HITOC.Models.ContractViewModel
@{
ViewBag.Title = "Create";
}
<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>
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$('#contract_ContractNo_Letter').setMask({ mask: 'a' });
$('#contract_ContractNo_Number').setMask({ mask: '999', type: 'reverse' });
$('#contract_ContractPeriodInWeeks').setMask({ mask: '999', type: 'reverse' });
$('#contract_ContractValue').setMask({ mask: '99.999999999999', type: 'reverse', defaultValue: '000' });
});
</script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<h1>CREATE an Instruction to Open File Form</h1>
<hr />
<p>DIRECTOR OR HEAD OF DIVISION <b>ONLY</b> TO INSTRUCT</p>
<fieldset>
<legend>Enter the contract details here:</legend>
<p>Where you see <span class="error">*</span> you must enter data.</p>
<table>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.SignOffDate)<span class="error">*</span>
</td>
<td>
@Html.EditorFor(model => model.contract.SignOffDate)
@Html.ValidationMessageFor(model => model.contract.SignOffDate)
</td>
</tr>
<tr>
<th colspan="2">-- Enter Contract Number</th>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ContractTypeId)<span class="error">*</span>
</td>
<td>
@Html.DropDownListFor(model => model.contract.ContractTypeId, Model.contractTypesSelectList, "<--Select-->")
@Html.ValidationMessageFor(model => model.contract.ContractTypeId)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ContractNo_Letter)<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.contract.ContractNo_Letter,
new { autocomplete = "off", maxlength = "1", style = "width:15px;text-transform: uppercase;" })
@Html.ValidationMessageFor(model => model.contract.ContractNo_Letter)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ContractNo_Number)<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.contract.ContractNo_Number,
new { autocomplete = "off", maxlength = "3", style = "width:30px;" })
@Html.ValidationMessageFor(model => model.contract.ContractNo_Number)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ContractNo_Suffix)
</td>
<td>
@Html.TextBoxFor(model => model.contract.ContractNo_Suffix,
new { maxlength = "2", style = "width:30px;text-transform: uppercase;" })
</td>
</tr>
<tr>
<th colspan="2">-- Enter Estimate and Order Details</th>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.EstimateNumber)<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.contract.EstimateNumber,
new { autocomplete = "off", style = "text-transform: uppercase;" })
@Html.ValidationMessageFor(model => model.contract.EstimateNumber)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ClientOrderNumber)
</td>
<td>
@Html.EditorFor(model => model.contract.ClientOrderNumber)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.InstructionWithoutClientOrder)<br />
(Only if no Client Order Number)
</td>
<td>
@Html.TextAreaFor(model => model.contract.InstructionWithoutClientOrder,
new { maxlength = "255", style = "width:200px;height:100px;"})
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.GivenDate)<span class="error">*</span>
</td>
<td>
@Html.EditorFor(model => model.contract.GivenDate)
@Html.ValidationMessageFor(model => model.contract.GivenDate)
</td>
</tr>
<tr>
<th colspan="2">-- Enter Client Details</th>
</tr>
<tr>
<td align="right">
Client Organisation Name<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.clientContact.ContactName, new { autocomplete = "off", style = "text-transform: capitalize;" })
@Html.ValidationMessageFor(model => model.clientContact.ContactName)
</td>
</tr>
<tr>
<td align="right">
Client Address<span class="error">*</span>
</td>
<td>
@Html.EditorFor(model => model.clientContact.AddressLine1)
@Html.ValidationMessageFor(model => model.clientContact.AddressLine1)
</td>
</tr>
<tr>
<td></td>
<td>
@Html.EditorFor(model => model.clientContact.AddressLine2)
</td>
</tr>
<tr>
<td align="right">
Post code<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.clientContact.PostCode,
new { autocomplete = "off", style = "text-transform: uppercase;" })
@Html.ValidationMessageFor(model => model.clientContact.PostCode)
</td>
</tr>
<tr>
<td align="right">
Name of contact
</td>
<td>
@Html.TextBoxFor(model => model.clientContact.NameOfContact, new { autocomplete = "off", style = "text-transform: capitalize;" })
@Html.ValidationMessageFor(model => model.clientContact.NameOfContact)
</td>
</tr>
<tr>
<td align="right">
Tel No
</td>
<td>
@Html.EditorFor(model => model.clientContact.Phone)
@Html.ValidationMessageFor(model => model.clientContact.Phone)
</td>
</tr>
<tr>
<th colspan="2">-- Enter Contract Administrator Details</th>
</tr>
<tr>
<td></td>
<td><input id="chkCopyContact" type="checkbox" name="chkCopyContact" /> Click here to copy across the client contact details </td>
</tr>
<tr>
<td align="right">
Name<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.contractAdministratorContact.ContactName, new { autocomplete = "off", style = "text-transform: capitalize;" })
@Html.ValidationMessageFor(model => model.contractAdministratorContact.ContactName)
</td>
</tr>
<tr>
<td align="right">
Address<span class="error">*</span>
</td>
<td>
@Html.EditorFor(model => model.contractAdministratorContact.AddressLine1)
@Html.ValidationMessageFor(model => model.contractAdministratorContact.AddressLine1)
</td>
</tr>
<tr>
<td></td>
<td>
@Html.EditorFor(model => model.contractAdministratorContact.AddressLine2)
</td>
</tr>
<tr>
<td align="right">
Post code<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.contractAdministratorContact.PostCode,
new { autocomplete = "off", style = "text-transform: uppercase;" })
@Html.ValidationMessageFor(model => model.contractAdministratorContact.PostCode)
</td>
</tr>
<tr>
<td align="right">
Name of contact
</td>
<td>
@Html.TextBoxFor(model => model.contractAdministratorContact.NameOfContact,
new { autocomplete = "off", style = "text-transform: capitalize;" })
@Html.ValidationMessageFor(model => model.contractAdministratorContact.NameOfContact)
</td>
</tr>
<tr>
<td align="right">
Tel No
</td>
<td>
@Html.EditorFor(model => model.contractAdministratorContact.Phone)
@Html.ValidationMessageFor(model => model.contractAdministratorContact.Phone)
</td>
</tr>
<tr>
<th colspan="2">-- Enter Contract Title/Address</th>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ContractTitle)<span class="error">*</span>
</td>
<td>
@Html.EditorFor(model => model.contract.ContractTitle)
@Html.ValidationMessageFor(model => model.contract.ContractTitle)
</td>
</tr>
<tr>
<td></td>
<td>
@Html.EditorFor(model => model.contract.ContractAddressLine1)
</td>
</tr>
<tr>
<td></td>
<td>
@Html.EditorFor(model => model.contract.ContractAddressLine2)
</td>
</tr>
<tr>
<td align="right">
Post code<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.contract.ContractPostCode,
new { autocomplete = "off", style = "text-transform: uppercase;" })
@Html.ValidationMessageFor(model => model.contract.ContractPostCode)
</td>
</tr>
<tr>
<th colspan="2">-- Enter Work Description</th>
</tr>
<tr>
<td align="right"><span class="error">*</span></td>
<td >
@Html.TextAreaFor(model => model.contract.WorkDescription,
new { maxlength = "255", style = "width:200px;height:100px;" })
@Html.ValidationMessageFor(model => model.contract.WorkDescription)
</td>
</tr>
<tr>
<th colspan="2">-- Enter Contract Details</th>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.StartDate)
</td>
<td>
@Html.EditorFor(model => model.contract.StartDate)
@Html.ValidationMessageFor(model => model.contract.StartDate)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ContractPeriodInWeeks)<span class="error">*</span>
</td>
<td>
@Html.TextBoxFor(model => model.contract.ContractPeriodInWeeks, new { style = "width:30px" })
@Html.ValidationMessageFor(model => model.contract.ContractPeriodInWeeks)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.OperationsManagerUserId)<span class="error">*</span>
</td>
<td>
@Html.DropDownListFor(model => model.contract.OperationsManagerUserId, Model.operationManagerSelectList, "<--Select-->")
@Html.ValidationMessageFor(model => model.contract.OperationsManagerUserId)
</td>
</tr>
<tr>
<td align="right">
@Html.LabelFor(model => model.contract.ContractValue)
</td>
<td>
@Html.TextBoxFor(model => model.contract.ContractValue, new {style = "width:120px" })
(Leave as zero if not decided yet).
@Html.ValidationMessageFor(model => model.contract.ContractValue)
</td>
</tr>
<tr>
<td align="center" colspan="2" style="padding-top:20px;"><input type="submit" value="Create" /></td>
</tr>
</table>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "List")
</div>
Your view model doesn't make sense. You are putting Required attribute on a non-nullable integer property which will have always a value (0 in your case). So start by modifying your view model:
[DisplayName("Contract Prefix")]
[UIHint("DropDownList")]
[Required(ErrorMessage = "You must select a Contract Prefix")]
public int? ContractTypeId { get; set; }
Now you can have dropdown lists with null values:
@Html.DropDownListFor(
x => x.contract.ContractTypeId,
Model.contractTypesSelectList,
"<--Select-->"
)
@Html.ValidationMessageFor(x => x.contract.ContractTypeId)
Then if you want to do client side validation in ASP.NET MVC 3, jQuery and the jQuery validate plugins are used for this. So make sure you have included the following scripts to your page:
- jquery.validate.js
- jquery.validate.unobtrusive.js
Also make sure that your controller action receives properly the selected value:
[HttpPost]
public ActionResult Foo(MyViewModel model)
{
if (!ModelState.IsValid)
{
// there was an error => redisplay the view
return View(model);
}
// model.contract.ContractTypeId will contain a value
// at this stage here => use it to do some processing
...
}
精彩评论