Post multiple data from an loaded form ajax mvc 4 - ajax

I have a form like this
<table>
<thead>
<tr>
<th>Tên học sinh </th>
<th>Giáo lý viên </th>
<th>Năm Học</th>
<th>Điểm TB Học Kỳ 1 </th>
<th>Điểm TB Học Kỳ 2 </th>
<th>Điểm Tổng Kết Năm Học </th>
<th>Lớp </th>
</tr>
</thead>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset class="form-horizontal">
<tbody id="addDetails">
<tr>
<td>
#Html.DropDownList("HocSinhId", String.Empty)
#Html.ValidationMessageFor(model => model.HocSinhId, null, new { #class = "help-inline" })
</td>
<td>
#Html.DropDownList("GiaoLyVienId", String.Empty)
#Html.ValidationMessageFor(model => model.GiaoLyVienId, null, new { #class = "help-inline" })
</td>
<td>
#Html.TextBoxFor(model => model.NamHoc)
#Html.ValidationMessageFor(model => model.NamHoc, null, new { #class = "help-inline" })
</td>
<td>
#Html.EditorFor(model => model.DiemTBHK1)
#Html.ValidationMessageFor(model => model.DiemTBHK1, null, new { #class = "help-inline" })
</td>
<td>
#Html.EditorFor(model => model.DiemTBHK2)
#Html.ValidationMessageFor(model => model.DiemTBHK2, null, new { #class = "help-inline" })
</td>
<td>
#Html.EditorFor(model => model.DiemTongKetNamHoc)
#Html.ValidationMessageFor(model => model.DiemTongKetNamHoc, null, new { #class = "help-inline" })
</td>
<td>
#Html.DropDownList("LopId", String.Empty)
#Html.ValidationMessageFor(model => model.LopId, null, new { #class = "help-inline" })
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
#Ajax.ActionLink("Add", "AddDetails", new AjaxOptions
{
HttpMethod = "GET",
OnSuccess = "successCall",
#*UpdateTargetId = "addDetails",
InsertionMode = InsertionMode.InsertAfter,*#
})
</td>
</tr>
<tr>
<td colspan="6">
#* *#
<input type="submit" value="Lưu thông tin" class="button" />
</td>
</tr>
</tfoot>
</fieldset>
}
</table>
After click Ajax link "Add" it will insert new row to input new data.
Image: http://i808.photobucket.com/albums/zz1/nquangkhaiDST/Postmultipledata_zps5364f0a0.png
The Question is: When I submit to server, it just post the first data, not the data after i click "Add". How i can get all the data even field from ajax to post back to server.
Anyone know how to post all the data even the data of ajax. Thanks a lots

Assuming you'll be adding that same type of object when you click Add, what you need to do is accept an array of your model object in your Post controller parameter.
[HttpPost]
public ActionResult(MyObject[] objects)
{
// do something
}

did you check your html on client side.... while submitting from client side you have to make sure that that the controls added on the page must have naming convention like
<input type="text" value="" name="IncomeDetails[0].IncomeCode" id="IncomeDetails_0__IncomeCode" class="incomeCode valid" disabled="disabled">
on the first row and
<input type="text" disabled="disabled" class="incomeCode valid" id="IncomeDetails_1__IncomeCode" name="IncomeDetails[1].IncomeCode" value="">
on the second row then only while submitting you can get full list of objects.

Related

PartialView is not working (whole page refresh instead)

Hello I am new to MVC 4. I am having a problem with partialView.. I goole it and searched alot and studied different tutorials but couldn't find any solution that can address my problem.I created a PagedList to display records at Index.cshtml page. Then I created PartialIndex.cshtml page to display records in Partial View.
Here is problem: When I click on any page number or navigate.. whole page refreshes and post back... partial view is not working.Don't Know where I am doing wrong.
I want to show table inside the DIV in PartialIndex.cshtml
PartialIndex.cshtml:
<div id="targetContainer"> //I want to show this DIV in partial view.
<table>
<tr>
<th>
#Html.ActionLink("ID", "Index", new { sortOrder = ViewBag.customerID, currentFilter=ViewBag.CurrentFilter })
</th>
<th>
</th>
<th>
#Html.DisplayName("First Name")
</th>
<th></th>
<th>
#Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.lName, currentFilter=ViewBag.CurrentFilter })
</th>
<th></th>
<th>
#Html.DisplayName("Contact Num")
</th>
<th>
#Html.DisplayName("Address")
</th>
<th>
#Html.DisplayName("Email")
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.customerId)
</td>
<td>
</td>
<td>
#Html.DisplayFor(modelItem => item.fName)
</td>
<td>
</td>
<td>
#Html.DisplayFor(modelItem => item.lName)
</td>
<td>
</td>
<td>
#Html.DisplayFor(modelItem => item.contactNum)
</td>
<td>
</td>
<td>
#Html.DisplayFor(modelItem => item.address)
</td>
<td>
</td>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID })
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
</div>
<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(
new AjaxOptions { InsertionMode = InsertionMode.Replace, HttpMethod = "GET", UpdateTargetId = "targetContainer" }))
Index.cshtml:
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.Partial("PartialIndex")
You should better use
Html.RenderPartial("~/Views/Shared/_Yourpartial.cshtml")
Html.RenderPartial("~/Views/Shared/PartialIndex.cshtml")

create and index views combined in 1 view

I want to be able to add players and upon addition in the same I want to display them in a table similar to what page Index view offers. so what I did is combine the index and create views in 1 page.
but when debugging I'm have a resource cannot be found error.
can some one please correct where I'm going wrong
Index View:
#model IEnumerable<sportsMania.player>
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>category</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.Label("Player Name")
<div class="col-md-10">
#Html.Editor("Player Name")
</div>
</div>
<div class="form-group">
#Html.Label("Team")
<div class="col-md-10">
#Html.DropDownList("team", ViewBag.team as SelectList)
</div>
</div>
<div class="form-group">
#Html.Label("Position")
<div class="col-md-10">
#Html.Editor("position")
</div>
</div>
<div class="form-group">
#Html.Label("Email")
<div class="col-md-10">
#Html.Editor("email")
</div>
</div>
<div class="form-group">
#Html.Label("Type")
<div class="col-md-10">
#Html.Editor("type")
</div>
</div>
<div class="form-group">
#Html.Label("Height")
<div class="col-md-10">
#Html.Editor("height")
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.playerName)
</th>
<th>
#Html.DisplayNameFor(model => model.team)
</th>
<th>
#Html.DisplayNameFor(model => model.position)
</th>
<th>
#Html.DisplayNameFor(model => model.email)
</th>
<th>
#Html.DisplayNameFor(model => model.type)
</th>
<th>
#Html.DisplayNameFor(model => model.height)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.playerName)
</td>
<td>
#Html.DisplayFor(modelItem => item.team)
</td>
<td>
#Html.DisplayFor(modelItem => item.position)
</td>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
<td>
#Html.DisplayFor(modelItem => item.type)
</td>
<td>
#Html.DisplayFor(modelItem => item.height)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>
playerController:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace sportsMania.Controllers
{
public class playerController : Controller
{
sportsEntities db = new sportsEntities();
[HttpPost]
public ActionResult Index()
{
var data = from p in db.Teams
select p.teamName;
SelectList list = new SelectList(data);
ViewBag.team = list;
return View(db.players.ToList());
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(player player)
{
if (ModelState.IsValid)
{
player newRecord = new player();
newRecord.playerName = Request.Form["Player Name"];
newRecord.position = Request.Form["position"];
newRecord.type =Request.Form[ "type"];
newRecord.team =Request.Form[ "team"];
newRecord.email = Request.Form["email"];
newRecord.height = Request.Form["height"];
db.players.Add(player);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(player);
}
}
}
why I am doing this? because I don't want every time the user have to add a Player he should be redirected to the create view, I want when user finishes adding players he will hit a button "done adding" and will be redirected home.

Partial view renders as full view

MVC 3 , ajax, c#
My partial view is rendering as a new page instead of replacing the search results table.
Controller:
public class SearchController : Controller
{
//
// GET: /Search/
private myEntities db = new myEntities();
private Repository repo = new Repository();
[HttpGet]
public ActionResult Index()
{
var model = new List<PersonViewModel>();
model = repo.GetPeople();
return View(model);
}
public PartialViewResult _SearchResult(string fname, string lname)
{
var personResult = repo.GetSearchResult(fname, lname);
return PartialView("_SearchResult", personResult);
}
}
The view:
<div class="page">
<div class="middle-col-comment-mod">
<h2>Search Existing Trespassers</h2>
<div id="search">
#using (Ajax.BeginForm("_SearchResult", "Search", null, new AjaxOptions { HttpMethod = "Post", InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace, UpdateTargetId = "indexSearchResults" }))
{
<div class="editor-field">
<label>First Name:</label>
#Html.TextBox("FirstName")
<label style = "margin-left: 15px;">Last Name:</label>
#Html.TextBox("LastName", "", new { style = "margin-right: 15px;" })
<input type="submit" name="submit" class="skbutton" value="Search" />
</div>
}
</div>
<table id="indexSearchResults" class="data-table">
<tr>
<th>
FirstName
</th>
<th>
LastName
</th>
<th>
Gender
</th>
<th>
City
</th>
<th>
DOB
</th>
<th>
IsStudent
</th>
<th>
Actions
</th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan=7>
There are currently no trespassers in the trespass database.
</td>
</tr>
}
else
{
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Gender)
</td>
<td>
#Html.DisplayFor(modelItem => item.DOB)
</td>
<td>
#Html.DisplayFor(modelItem => item.School)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsStudent)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.PersonId }) |
#Html.ActionLink("Details", "Details", new { id = item.PersonId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.PersonId })
</td>
</tr>
}
}
</table>
</div>
</div>
And the partial view:
#model IEnumerable<TrespassTracker.Models.PersonViewModel>
<table>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Gender
</th>
<th>
Date of Birth
</th>
<th>
Is a Student?
</th>
<th>
Actions
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Gender)
</td>
<td>
#Html.DisplayFor(modelItem => item.DOB)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsStudent)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
From my research I found the usual suspect to be the missing link to the jquery script in the partial, but I had that. I checked the network tab on my wed dev tools and found it is being called. What else could the problem be?
the script won't cause any problem and the only thing I see wrong here is the table. you are trying yo fill the table with other table which returns a table, use a div instead to update the ajax form (search result):
<div id="indexSearchResults">
<table>
..........
</table>
</div>
Try this
<div class="page">
<div class="middle-col-comment-mod">
<h2>Search Existing Trespassers</h2>
<div id="search">
#using (Ajax.BeginForm("_SearchResult", "Search", null, new AjaxOptions { HttpMethod = "Post", InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace, UpdateTargetId = "indexSearchResults" }))
{
<div class="editor-field">
<label>First Name:</label>
#Html.TextBox("FirstName")
<label style = "margin-left: 15px;">Last Name:</label>
#Html.TextBox("LastName", "", new { style = "margin-right: 15px;" })
<input type="submit" name="submit" class="skbutton" value="Search" />
</div>
}
</div>
#if (Model.Count() == 0)
{
<label>There are currently no trespassers in the trespass database. </label>
}
else
{
foreach (var item in Model)
{
#Html.Partial("__SearchResult",item)
}
</div>
</div>
How 'bout to use jQuery do reload your result content, instead Post from your form? You can named some div with an ID and uses it as reference do jQuery.load() (considering you're using that ViewModel you passed into Index action):
1.View
#model YourModel
<!-- ... -->
<div id="search">
#using (Ajax.BeginForm("MainPostAction", "ControllerName", FormMethod.Post, new { id = "yourFormID" })
{
<div class="editor-field">
<label>First Name:</label>
#Html.TextBoxFor(model => model.FirstName)
<label style = "margin-left: 15px;">Last Name:</label>
#Html.TextBoxFor(model => model.LastName, new { style = "margin-right: 15px;" })
<input type="button" name="submit" id="searchButton" class="skbutton" value="Search" />
</div>
<div id="results"></div>
}
</div>
Javascript:
$(document).ready(function() {
$('#searchButton').click(function(event) {
$('#results').load('#Url.Action('_SearchResult', 'Search')', $('#yourFormID').serialize());
});
}
Your action remains the same.
How 'bout it?

MVC 3 using partial view to add a new listing with ajax

REVISED BUT SAME ISSUE:
I am building a site with MVC 3 and have run into a big road block. On the profile page, users will have the ability to create a new listing offered by their center. I have created this using a partial view for the "_CenterProfile" portion of the page which works perfectly. I've implemented the Create Listing as the main focus of the page and model which also works perfectly. I would like to use Ajax to create the database entries as well as populate or update the Listings shown on the Profile page. This is where the problem comes in.
When I click the submit button, rather than updating the targeted element, the page flips to a non existent "CreateListing" page ../Exchange/CreateListing. I'm going crazy trying to get this to function and no matter what I try it does the same thing. The Listing is populated to the database and the page changes from /Exchange/Profile to /Exchange/CreateListing.
I'm sure someone out there can help me, I'm on a deadline and getting past this headache will save me big time.
"Profile" View:
#model Exchange.Models.CreateListingModel
#{
ViewBag.Title = "Profile";
}
<h2>Profile</h2>
#Html.Action("_CenterProfile")
<br />
#using (Ajax.BeginForm("CreateListing", "Exchange", new AjaxOptions
{
HttpMethod = "Get",
UpdateTargetId = "centerListings",
InsertionMode = InsertionMode.Replace
}))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>CreateListingModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.productName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.productName)
#Html.ValidationMessageFor(model => model.productName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.forSale)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.forSale)
#Html.ValidationMessageFor(model => model.forSale)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.forTrade)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.forTrade)
#Html.ValidationMessageFor(model => model.forTrade)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.price)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.price)
#Html.ValidationMessageFor(model => model.price)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.unit)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.unit)
#Html.ValidationMessageFor(model => model.unit)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.catagoryID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.catagoryID)
#Html.ValidationMessageFor(model => model.catagoryID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.description)
#Html.ValidationMessageFor(model => model.description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.imageURL)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.imageURL)
#Html.ValidationMessageFor(model => model.imageURL)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.activeListing)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.activeListing)
#Html.ValidationMessageFor(model => model.activeListing)
</div>
</fieldset>
<p>
<input type="submit" value="CreateListing" />
</p>
}
<table id="centerListings">
</table>
<p>
#Html.ActionLink("Edit", "Edit", new { /* id=Model.PrimaryKey */ }) |
#Html.ActionLink("Back to List", "Index")
</p>
CreateListing Controller:
public PartialViewResult CreateListing(CreateListingModel model)
{
mmjc.CreateListing(model.catagoryID, model.productName, model.forSale, model.forTrade, model.price, model.unit, model.description, model.imageURL, model.activeListing);
var listings = mmjc.GetCenterListings();
return PartialView("_CenterListings", listings);
}
_CenterListings PartialView:
#model IEnumerable<Exchange.Models.Listing>
<table id="centerListings">
<tr>
<th>
CatagoryID
</th>
<th>
ProductName
</th>
<th>
ToSell
</th>
<th>
ToTrade
</th>
<th>
PricePerUnit
</th>
<th>
Unit
</th>
<th>
Description
</th>
<th>
ImgPath
</th>
<th>
ProfileID
</th>
<th>
ActiveListing
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CatagoryID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProductName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ToSell)
</td>
<td>
#Html.DisplayFor(modelItem => item.ToTrade)
</td>
<td>
#Html.DisplayFor(modelItem => item.PricePerUnit)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.ImgPath)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProfileID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ActiveListing)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ListingsID }) |
#Html.ActionLink("Details", "Details", new { id=item.ListingsID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ListingsID })
</td>
</tr>
}
</table>
I think you should provide an UpdateTargetId in your AjaxOptions:
new AjaxOptions { HttpMethod = "Post",
UpdateTargetId = "idOfSomeHtmlContainer" }
With this property you specify which part of the page should be updated with the response from the AJAX call. Using the code you have now, ASP.NET MVC doesn't know which part of the page to update with the view returned from your action method.
Ok everyone. So I fixed my own problem here. It seems many people are having this same issue. The fix is so easy it made me feel very silly.
All you have to do is include
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
In your _Layout or Main View. Without it the Ajax.BeginForm is useless and will continue to redirect to the PartialViewResult.
I think you want to specify the necessary Ajax options to replace the content of the create listing form- namely the Id of the element to replace and the update mode.

MVC3: How do I validate a drop down list?

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
...
}

Resources