IEnumerable is null when I expect values - asp.net-mvc

I am using the approach in this article to return a list of objects that are posted to my action. My method looks like:
//
// POST: /LeaveRequest/Create
[Authorize, HttpPost]
public ActionResult Create(LeaveRequest leaveRequest, IEnumerable<DayRequested> requestedDays)
{
return RedirectToAction("Index", lrRepository.GetLeaveRequests(472940821));
}
leaveRequest has the data that I expect. requestedDays contains the number of rows I expect, but all of the rows contain null in each field. Any ideas of what I may be missing?
Here is the View code:
Create.aspx
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<EmployeePayroll.ViewModels.LeaveRequestViewModel>" %>
<%# Import Namespace="EmployeePayroll.Helpers"%>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">Create New Leave Request</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create New Leave Request</h2>
<div><%= Html.ActionLink("Back to List", "Index") %></div>
<%= Html.Partial("RequestEditor", Model) %>
<div><%= Html.ActionLink("Back to List", "Index") %></div>
</asp:Content>
RequestEditor.ascx
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<EmployeePayroll.ViewModels.LeaveRequestViewModel>" %>
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Request Details</legend>
<table>
<tbody id="editorRows">
<tr><th>Date</th><th>Time</th><th>Hours</th><th>Request Type</th><th></th></tr>
<% foreach (var item in Model.DaysRequested)
Html.RenderPartial("RequestedDayRow", new EmployeePayroll.ViewModels.LeaveRequestRow(item, Model.LeaveRequestType)); %>
</tbody>
</table>
<p><%= Html.ActionLink("Add Day", "BlankRequestedDayRow", null, new { id = "addItem" })%></p>
<p>Type your time to sign your request.</p>
<p><%= Html.LabelFor(model => model.LeaveRequest.EmployeeSignature) %>: <%= Html.TextBoxFor(model => model.LeaveRequest.EmployeeSignature, new { Class="required" })%></p>
<p><%= Html.LabelFor(model => model.LeaveRequest.EmployeeComment) %>: <%= Html.TextBoxFor(model => model.LeaveRequest.EmployeeComment) %></p>
<p><input type="submit" value="Submit Request" /></p>
</fieldset>
<% } %>
RequestedDayRow.ascx
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<EmployeePayroll.ViewModels.LeaveRequestRow>" %>
<%# Import Namespace="EmployeePayroll.Helpers"%>
<tr class="editorRow">
<% using (Html.BeginCollectionItem("requestedDays"))
{ %>
<td><%= Html.TextBoxFor(model => model.DayRequested.DateOfLeave, new { Class = "datepicker", Maxlength = "10" })%></td>
<td><%= Html.TextBoxFor(model => model.DayRequested.TimeOfLeave, new { Class = "timedropdown", Maxlength = "8" })%></td>
<td><%= Html.TextBoxFor(model => model.DayRequested.HoursRequested, new { Class = "hoursdropdown", Maxlength = "4" })%></td>
<td><%= Html.DropDownListFor(model => model.DayRequested.RequestType,
new SelectList(Model.LeaveRequestType, "Value", "Text", Model.DayRequested.RequestType), "(Select)")%></td>
<td><img src="../../images/site_icons/16/69.png" title="Delete" alt="Delete" border="0" /></td>
<% } %>
</tr>
Here is the generated form:
<form method="post" action="/LeaveRequest/Create">
<fieldset>
<legend>Request Details</legend>
<table>
<tbody id="editorRows">
<tr><th>Date</th><th>Time</th><th>Hours</th><th>Request Type</th><th></th></tr>
<tr class="editorRow">
<input type="hidden" value="c43391a3-7fe4-4514-8b27-d00995d64848" autocomplete="off" name="requestedDays.index">
<td><input type="text" value="11/17/2010" name="requestedDays[c43391a3-7fe4-4514-8b27-d00995d64848].DayRequested.DateOfLeave" id="requestedDays_c43391a3-7fe4-4514-8b27-d00995d64848__DayRequested_DateOfLeave" maxlength="10" class="datepicker"></td>
<td><input type="text" value="8:00 AM" name="requestedDays[c43391a3-7fe4-4514-8b27-d00995d64848].DayRequested.TimeOfLeave" id="requestedDays_c43391a3-7fe4-4514-8b27-d00995d64848__DayRequested_TimeOfLeave" maxlength="8" class="timedropdown"></td>
<td><input type="text" value="8" name="requestedDays[c43391a3-7fe4-4514-8b27-d00995d64848].DayRequested.HoursRequested" id="requestedDays_c43391a3-7fe4-4514-8b27-d00995d64848__DayRequested_HoursRequested" maxlength="4" class="hoursdropdown"></td>
<td><select name="requestedDays[c43391a3-7fe4-4514-8b27-d00995d64848].DayRequested.RequestType" id="requestedDays_c43391a3-7fe4-4514-8b27-d00995d64848__DayRequested_RequestType"><option value="">(Select)</option>
</select></td>
<td><a class="deleteRow" href="#"><img border="0" alt="Delete" title="Delete" src="../../images/site_icons/16/69.png"></a></td>
</tr>
<tr class="editorRow">
<input type="hidden" value="a24b74f6-2947-4ec5-a817-f938d6fe4e24" autocomplete="off" name="requestedDays.index">
<td><input type="text" value="11/17/2010" name="requestedDays[a24b74f6-2947-4ec5-a817-f938d6fe4e24].DayRequested.DateOfLeave" id="requestedDays_a24b74f6-2947-4ec5-a817-f938d6fe4e24__DayRequested_DateOfLeave" maxlength="10" class="datepicker"></td>
<td><input type="text" value="8:00 AM" name="requestedDays[a24b74f6-2947-4ec5-a817-f938d6fe4e24].DayRequested.TimeOfLeave" id="requestedDays_a24b74f6-2947-4ec5-a817-f938d6fe4e24__DayRequested_TimeOfLeave" maxlength="8" class="timedropdown"></td>
<td><input type="text" value="8" name="requestedDays[a24b74f6-2947-4ec5-a817-f938d6fe4e24].DayRequested.HoursRequested" id="requestedDays_a24b74f6-2947-4ec5-a817-f938d6fe4e24__DayRequested_HoursRequested" maxlength="4" class="hoursdropdown"></td>
<td><select name="requestedDays[a24b74f6-2947-4ec5-a817-f938d6fe4e24].DayRequested.RequestType" id="requestedDays_a24b74f6-2947-4ec5-a817-f938d6fe4e24__DayRequested_RequestType"><option value="">(Select)</option>
</select></td>
<td><a class="deleteRow" href="#"><img border="0" alt="Delete" title="Delete" src="../../images/site_icons/16/69.png"></a></td>
</tr>
</tbody>
</table>
<p><a id="addItem" href="/LeaveRequest/BlankRequestedDayRow">Add Day</a></p>
<p>Type your time to sign your request.</p>
<p><label for="LeaveRequest_EmployeeSignature">Employee Signature</label>: <input type="text" value="" name="LeaveRequest.EmployeeSignature" id="LeaveRequest_EmployeeSignature" class="required"></p>
<p><label for="LeaveRequest_EmployeeComment">Employee Comment</label>: <input type="text" value="" name="LeaveRequest.EmployeeComment" id="LeaveRequest_EmployeeComment"></p>
<p><input type="submit" value="Submit Request"></p>
</fieldset>
</form>
The form posts the following information:
Parametersapplication/x-www-form-urlencoded
LeaveRequest.EmployeeComm... Comment
LeaveRequest.EmployeeSign... Michael Wills
requestedDays.index 549a7c9a-9c7d-4032-a1cd-6bfda92bf1f2
requestedDays.index 2838b025-d971-4d98-a081-5ea0c559aebb
requestedDays[2838b025-d9... 11/17/2010
requestedDays[2838b025-d9... 8
requestedDays[2838b025-d9... 1
requestedDays[2838b025-d9... 8:00 AM
requestedDays[549a7c9a-9c... 11/17/2010
requestedDays[549a7c9a-9c... 8
requestedDays[549a7c9a-9c... 1
requestedDays[549a7c9a-9c... 8:00 AM
Source
Content-Type: application/x-www-form-urlencoded
Content-Length: 907
requestedDays.index=549a7c9a-9c7d-4032-a1cd-6bfda92bf1f2&requestedDays%5B549a7c9a-9c7d-4032-a1cd-6bfda92bf1f2%5D.DayRequested.DateOfLeave=11%2F17%2F2010&requestedDays%5B549a7c9a-9c7d-4032-a1cd-6bfda92bf1f2%5D.DayRequested.TimeOfLeave=8%3A00+AM&requestedDays%5B549a7c9a-9c7d-4032-a1cd-6bfda92bf1f2%5D.DayRequested.HoursRequested=8&requestedDays%5B549a7c9a-9c7d-4032-a1cd-6bfda92bf1f2%5D.DayRequested.RequestType=1&requestedDays.index=2838b025-d971-4d98-a081-5ea0c559aebb&requestedDays%5B2838b025-d971-4d98-a081-5ea0c559aebb%5D.DayRequested.DateOfLeave=11%2F17%2F2010&requestedDays%5B2838b025-d971-4d98-a081-5ea0c559aebb%5D.DayRequested.TimeOfLeave=8%3A00+AM&requestedDays%5B2838b025-d971-4d98-a081-5ea0c559aebb%5D.DayRequested.HoursRequested=8&requestedDays%5B2838b025-d971-4d98-a081-5ea0c559aebb%5D.DayRequested.RequestType=1&LeaveRequest.EmployeeSignature=Michael+Wills&LeaveRequest.EmployeeComment=Comment

Looks like you may need to remove DayRequested from your hidden form field name.
For example:
... I removed some of the attributes because the only thing that's changed here is the name attribute.
<input type="hidden" name="requestedDays[c43391a3-7fe4-4514-8b27-d00995d64848].DateOfLeave" value="11/17/2010" />
<input type="hidden" name="requestedDays[c43391a3-7fe4-4514-8b27-d00995d64848].TimeOfLeave" value="8:00 AM" />
<input type="hidden" name="requestedDays[c43391a3-7fe4-4514-8b27-d00995d64848].HoursRequested" value="8" />
...
As discussed in the question comments, it seems odd that ASP.NET MVC would generate the source you gave, as that suggests that each RequestedDay object has a single property called RequestedDay.
The object you're binding to is called requestedDays, and the guid is an indication of which position in the collection you're binding to (stating the obvious here, I know!). Therefore, stating the object name (DayRequested) doesn't make any sense, since the model binder should already know this, and just needs to know which property of that class it's dealing with.

see this post from Haacked - Model Binding To A List
it might help you

Related

Can one handle Multiple Post Form Actions on One View in MVC

Just need to if i can use to form=post in the mvc view , below is the example which uses to form post , which currently doesnt works:
Edited: the jquery is submiting the form with id frmWorldPay when the image is clicked
$("#pay").click(function () {
// $("#frmWorldPay").(function () {
if ($("#terms").attr("checked")) {
$("#frmWorldPay").submit();
alert("sss");
// return true;
} else {
alert("Please agree to the terms and conditions.");
return false;
}
});
<% using (Html.BeginForm()) {%>
<table id="cart" border="0" cellpadding="0" cellspacing="0">
<tr>
<th>
Event
</th>
<th>
Item
</th>
<th>
Quantity
</th>
</tr>
<%
foreach (var bookingItem in Model.BookingItems)
{%>
<tr>
<td>
<%: ViewBag.Name %>
</td>
<td>
<%: Product.Description %>
</td>
<td>
<%: bookingItem.Quantity%>
</td>
</tr></table>
<% } %>
<% { %> if (ViewBag.mode == "confirm")
{ %>
<input type="submit" value="Confirm" />
<% } %>
<form method="post" action="https://secure.wp3.rbsworldpay.com/wcc/purchase" id="frmWorldPay">
<input type="hidden" name="instId" value="01" />
<input type="hidden" name="cartId" value="<%: Model.GUID %>" />
<input type="hidden" name="currency" value="GBP" />
<input type="hidden" name="testMode" value="100" />
</form> if (ViewBag.mode == "Checkout")
{ %>
<div id="worldPayBtnWrap">
<p> <%: Html.CheckBox("terms") %> by ticking this box you are agreeing to our <%: Html.ActionLink("terms & conditions", "Terms", "About")%></p>
<input type="image" src="/content/images/btnWorldPay.png" alt="Pay via World Pay" id="pay" />
</div>
<% } %>
You can have multiple forms in one web page, but you can't nest them.
Your external form is nested inside the MVC form (the using (Html.BeginForm()) { }), so it won't work.
I have sorted out the issue , actually my input was in same post method , therfore only one form was posting while the other input was not posting , the above is modified which works fine , although it is not a clean solution , for the time being i will be happy to use , will clean it later on .:)

MVC; How do you avoid ID name collisions when using tabs?

There is a lot to commend MVC, but one problem I keep getting is ID name collisions.
I first noticed it when generating a grid using a foreach loop. With the help of SO I found the solution was to use Editor Templates.
Now I have the same problem with tabs.
I used this reference to find out how to use tabs; http://blog.roonga.com.au/search?updated-max=2010-06-14T19:27:00%2B10:00&max-results=1
The problem with my tabs is that I am using a date field with a date picker. In the example above, ID name collisions are avoided by referencing a generated unique Id of the container element. However for a datepicker, the ID of the container is irrelevant, only the ID of the date field matters. So what happens is that if I create my second tab the same as the first, when I update my second tab, the date on the first is updated.
So below is my View, and a partial view which displays the date. When I click the "Add Absence for 1 day button, I create a tab for that screen;
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/AdminAccounts.master"
Inherits="System.Web.Mvc.ViewPage<SHP.WebUI.Models.AbsenceViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
AbsenceForEmployee
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="AdminAccountsContent" runat="server">
<script type="text/javascript">
$(function () {
$('#tabs').tabs(
{ cache: true },
{
ajaxOptions: {
cache: false,
error: function (xhr, status, index, anchor) {
$(anchor.hash).html("Couldn't load this tab.");
},
data: {},
success: function (data, textStatus) { }
},
add: function (event, ui) {
//select the new tab
$('#tabs').tabs('select', '#' + ui.panel.id);
}
});
});
function addTab(title, uri) {
var newTab = $("#tabs").tabs("add", uri, title);
}
function closeTab() {
var index = getSelectedTabIndex();
$("#tabs").tabs("remove", index)
}
function getSelectedTabIndex() {
return $("#tabs").tabs('option', 'selected');
}
function RefreshList() {
$('#frmAbsenceList').submit();
}
</script>
<% using (Html.BeginForm()) {%>
<%: Html.AntiForgeryToken() %>
<fieldset>
<legend>Select an employee to edit absence record</legend>
<div style="padding-bottom:30px;padding-left:10px;">
<div class="span-7"><b>Name:</b> <%: Model.Employee.GetName() %></div>
<div class="span-6"><b>Division:</b><%: Model.DivisionName %></div>
<div class="span-6"><b>Department:</b> <%: Model.DepartmentName %></div></div>
<p>Attendance record for the year <%: Html.DropDownListFor(model => model.SelectedYearId, Model.YearList, new { onchange = "this.form.submit();" })%></p>
<div id="tabs">
<ul>
<li>Absence List</li>
</ul>
<div id="tabs-1">
<input id="btnAddOneDayTab" type="button" onclick="addTab('Add Absence (1 day)','<%= Url.Action("AddAbsenceOneDay", "Employee") %>')" value='Add Absence for 1 day' />
<input id="btnAddDateRangeTab" type="button" onclick="addTab('Add Absence (date range)','<%= Url.Action("AddAbsenceDateRange", "Employee") %>')" value='Add Absence for a range of dates' />
<hr />
<% Html.RenderPartial("ListAbsence", Model.ListEmployeeAbsenceThisYear); %>
</div>
</div>
</fieldset>
<% } %>
Add new date partial view ...
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.Models.EmployeeOtherLeaf>" %>
<% var unique = DateTime.Now.Ticks.ToString(); %>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$('#frmAddAbsenceOneDay<%= unique %> #NullableOtherLeaveDate').datepicker({ dateFormat: 'dd-MM-yy' });
$('#frmAddAbsenceOneDay<%= unique %> #MorningOnlyFlag').click(function () {
$('#frmAddAbsenceOneDay<%= unique %> #AfternoonOnlyFlag').attr('checked', false);
})
$('#frmAddAbsenceOneDay<%= unique %> #AfternoonOnlyFlag').click(function () {
$('#frmAddAbsenceOneDay<%= unique %> #MorningOnlyFlag').attr('checked', false);
})
});
var options = {
target: '#frmAddAbsenceOneDay<%= unique %>',
success: RefreshList
};
$(document).ready(function () {
$('#frmAddAbsenceOneDay<%= unique %>').ajaxForm(options);
});
</script>
<div id="AddAbsenceOnDay<%= unique %>">
<% using (Html.BeginForm("AddAbsenceOneDay", "Employee", FormMethod.Post,
new { id = "frmAddAbsenceOneDay" + unique }))
{ %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Add an absence for a day or half day</legend>
<table>
<tr>
<td><%: Html.LabelFor(model => model.OtherLeaveId)%></td>
<td>
<%: Html.DropDownListFor(model => model.OtherLeaveId, Model.SelectLeaveTypeList, "<--Select-->")%>
<%: Html.ValidationMessageFor(model => model.OtherLeaveId)%>
</td>
</tr>
<tr>
<td>
<%: Html.LabelFor(model => model.NullableOtherLeaveDate)%>
</td>
<td>
<%: Html.EditorFor(model => model.NullableOtherLeaveDate)%>
<%: Html.ValidationMessageFor(model => model.NullableOtherLeaveDate)%>
<%if (ViewData["ErrorDateMessage"] != null && ViewData["ErrorDateMessage"].ToString().Length > 0)
{ %>
<p class="error">
At <% Response.Write(DateTime.Now.ToString("T")); %>. <%: ViewData["ErrorDateMessage"]%>.
</p>
<%} %>
</td>
</tr>
<tr>
<td>
<%: Html.LabelFor(model => model.MorningOnlyFlag)%>
</td>
<td>
<%: Html.CheckBoxFor(model => model.MorningOnlyFlag)%>
<%: Html.ValidationMessageFor(model => model.MorningOnlyFlag)%>
</td>
</tr>
<tr>
<td>
<%: Html.LabelFor(model => model.AfternoonOnlyFlag)%>
</td>
<td>
<%: Html.CheckBoxFor(model => model.AfternoonOnlyFlag)%>
<%: Html.ValidationMessageFor(model => model.AfternoonOnlyFlag)%>
</td>
</tr>
</table>
<p>
<span style="padding-right:10px;"><input type="submit" value="Create" /></span><input type="button" value="Close" onclick="closeTab()" />
</p>
</fieldset>
<% } %>
</div>
You can see the ID of the date in the following HTML from Firebug
<div id="main">
<div id="adminAccounts">
<table>
<tbody><tr>
<td>
<div style="padding-top: 15px;">
// Menu removed
</div>
</td>
<td>
<script type="text/javascript">
$(function () {
$('#tabs').tabs(
{ cache: true },
{
ajaxOptions: {
cache: false,
error: function (xhr, status, index, anchor) {
$(anchor.hash).html("Couldn't load this tab.");
},
data: {},
success: function (data, textStatus) { }
},
add: function (event, ui) {
//select the new tab
$('#tabs').tabs('select', '#' + ui.panel.id);
}
});
});
function addTab(title, uri) {
var newTab = $("#tabs").tabs("add", uri, title);
}
function closeTab() {
var index = getSelectedTabIndex();
$("#tabs").tabs("remove", index)
}
function getSelectedTabIndex() {
return $("#tabs").tabs('option', 'selected');
}
function RefreshList() {
$('#frmAbsenceList').submit();
}
</script>
<form method="post" action="/Employee/AbsenceForEmployee?employeeId=1"><input type="hidden" value="8yGn2w+fgqSRsho/d+7FMnPWBtTbu96X4u1t/Jf6+4nDSNJHOPeq7IT9CedAjrZIAK/DgbNX6idtTd94XUBM5w==" name="__RequestVerificationToken">
<fieldset>
<legend>Select an employee to edit absence record</legend>
<div style="padding-bottom: 30px; padding-left: 10px;">
<div class="span-7"><b>Name:</b> xaviar caviar</div>
<div class="span-6"><b>Division:</b>ICT</div>
<div class="span-6"><b>Department:</b> ICT</div></div>
<p>Absence Leave record for the year <select onchange="this.form.submit();" name="SelectedYearId" id="SelectedYearId"><option value="2" selected="selected">2010/11</option>
</select></p>
<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
<li class="ui-state-default ui-corner-top">Absence List</li>
<li class="ui-state-default ui-corner-top"><span>Add Absence (1 day)</span></li><li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><span>Add Absence (1 day)</span></li></ul>
<div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">
<input type="button" value="Add Absence for 1 day" onclick="addTab('Add Absence (1 day)','/Employee/AddAbsenceOneDay')" id="btnAddOneDayTab">
<input type="button" value="Add Absence for a range of dates" onclick="addTab('Add Absence (date range)','/Employee/AddAbsenceDateRange')" id="btnAddDateRangeTab">
<hr>
<script type="text/javascript">
var options = {
target: '#AbsenceList'
};
$(document).ready(function() {
$('#frmAbsenceList').ajaxForm(options);
});
</script>
<div id="AbsenceList">
<table class="grid"><thead><tr><th class="sort_asc"></th><th>Leave Type</th><th>Morning Only</th><th>Afternoon Only</th><th>Day Amount</th><th>Date</th></tr></thead><tbody><tr class="gridrow"><td>Delete</td><td>Sickness</td><td>False</td><td>False</td><td>1</td><td>04/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>08/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Unpaid Compassionate</td><td>False</td><td>False</td><td>1</td><td>09/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>10/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>15/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>16/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>17/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>22/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>24/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Sickness</td><td>False</td><td>False</td><td>1</td><td>25/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>26/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>29/11/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>30/11/2010</td></tr><tr class="gridrow_alternate"><td>Delete</td><td>Unpaid Sickness</td><td>False</td><td>False</td><td>1</td><td>13/12/2010</td></tr><tr class="gridrow"><td>Delete</td><td>Compassionate</td><td>False</td><td>False</td><td>1</td><td>26/12/2010</td></tr></tbody></table>
<p></p><div class="pagination"><span class="paginationLeft">Showing 1 - 15 of 21 </span><span class="paginationRight">first | prev | next | last</span></div>
</div>
</div><div id="ui-tabs-2" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">
<div id="AddAbsenceOnDay634255177533718544">
<form method="post" id="frmAddAbsenceOneDay634255177533718544" action="/Employee/AddAbsenceOneDay">
<fieldset>
<legend>Add an absence for a day or half day</legend>
<table>
<tbody><tr>
<td><label for="OtherLeaveId">Leave Type</label></td>
<td>
<select name="OtherLeaveId" id="OtherLeaveId"><option value=""><--Select--></option>
<option value="1">Sickness</option>
<option value="2">Unpaid Sickness</option>
<option value="6">Compassionate</option>
<option value="7">Unpaid Compassionate</option>
<option value="8">Unauthorised</option>
<option value="9">Unpaid Unauthorised</option>
<option value="10">Other</option>
<option value="11">Unpaid Other</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="NullableOtherLeaveDate">Date</label>
</td>
<td>
<input type="text" value="" name="NullableOtherLeaveDate" id="NullableOtherLeaveDate" class="datePicker hasDatepicker">
</td>
</tr>
<tr>
<td>
<label for="MorningOnlyFlag">Morning Only</label>
</td>
<td>
<input type="checkbox" value="true" name="MorningOnlyFlag" id="MorningOnlyFlag"><input type="hidden" value="false" name="MorningOnlyFlag">
</td>
</tr>
<tr>
<td>
<label for="AfternoonOnlyFlag">Afternoon Only</label>
</td>
<td>
<input type="checkbox" value="true" name="AfternoonOnlyFlag" id="AfternoonOnlyFlag"><input type="hidden" value="false" name="AfternoonOnlyFlag">
</td>
</tr>
</tbody></table>
<p>
<span style="padding-right: 10px;"><input type="submit" value="Create"></span><input type="button" onclick="closeTab()" value="Close">
</p>
</fieldset>
</form>
</div>
</div><div id="ui-tabs-4" class="ui-tabs-panel ui-widget-content ui-corner-bottom">
<div id="AddAbsenceOnDay634255177583860349">
<form method="post" id="frmAddAbsenceOneDay634255177583860349" action="/Employee/AddAbsenceOneDay">
<fieldset>
<legend>Add an absence for a day or half day</legend>
<table>
<tbody><tr>
<td><label for="OtherLeaveId">Leave Type</label></td>
<td>
<select name="OtherLeaveId" id="OtherLeaveId"><option value=""><--Select--></option>
<option value="1">Sickness</option>
<option value="2">Unpaid Sickness</option>
<option value="6">Compassionate</option>
<option value="7">Unpaid Compassionate</option>
<option value="8">Unauthorised</option>
<option value="9">Unpaid Unauthorised</option>
<option value="10">Other</option>
<option value="11">Unpaid Other</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="NullableOtherLeaveDate">Date</label>
</td>
<td>
<input type="text" value="" name="NullableOtherLeaveDate" id="NullableOtherLeaveDate" class="datePicker hasDatepicker">
</td>
</tr>
<tr>
<td>
<label for="MorningOnlyFlag">Morning Only</label>
</td>
<td>
<input type="checkbox" value="true" name="MorningOnlyFlag" id="MorningOnlyFlag"><input type="hidden" value="false" name="MorningOnlyFlag">
</td>
</tr>
<tr>
<td>
<label for="AfternoonOnlyFlag">Afternoon Only</label>
</td>
<td>
<input type="checkbox" value="true" name="AfternoonOnlyFlag" id="AfternoonOnlyFlag"><input type="hidden" value="false" name="AfternoonOnlyFlag">
</td>
</tr>
</tbody></table>
<p>
<span style="padding-right: 10px;"><input type="submit" value="Create"></span><input type="button" onclick="closeTab()" value="Close">
</p>
</fieldset>
</form>
</div>
</div>
<div id="ui-tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div><div id="ui-tabs-3" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div></div>
</fieldset>
</form></td>
</tr>
</tbody></table></div>
<div id="footer">
</div>
</div>
If you have got this far(!), I have been asked for the controller, so here it is.
[Authorize(Roles = "Administrator, AdminAccounts, ManagerAccounts")]
public ActionResult AddAbsenceOneDay()
{
return View(new EmployeeOtherLeaf());
}
[HttpPost]
[Authorize(Roles = "Administrator, AdminAccounts, ManagerAccounts")]
public ActionResult AddAbsenceOneDay(EmployeeOtherLeaf _absence)
{
if (ModelState.IsValid)
{
_absence.EmployeeId = SessionObjects.EmployeeId;
_absence.OtherLeaveDate = _absence.NullableOtherLeaveDate.GetValueOrDefault(DateTime.Today);
Tuple<bool, string> errorInfo = _absence.IsDateValid();
if (errorInfo.Item1 == true)
{
_absence.AddAndSave();
ViewData["SuccessMessage"] = "Successfully Added.";
return View("EditAbsenceOneDay", _absence);
}
else
{
ViewData["ErrorDateMessage"] = errorInfo.Item2;
return View(_absence);
}
}
else
{
return View(_absence);
}
}
The problem seems to be that the DOM only has one entry for NullableOtherLeaveDate. This seems logical because of the use of ID. What you can to is add the hash to the ID as well. If you need to match that ID with any jQuery you can use partial selectors like this:
$('input[id*=NullableOtherLeaveDate]')
See jQuery Partial Selectors for more about that.
Now how the modal binder will bind that I'm not sure but you can probably implement partial matching in C# with no problems. If you want any help with this please post the relevant code of your action.
The answer to this other question suggests using editor templates instead of partials to solve the problem.
MVC - fields in a partial View need a Unique Id. How do you do this?
Of course this will not work for every situations, just the editor ones.
Update:
There is another easy way too. The ViewData has a nice property you can use to set a prefix that makes the partial unique, then this ViewDataDictonary can be passed to the partial.
var dataDictionary = new ViewDataDictionary<PersonModel>(Model.Persons.First);
dataDictionary.TemplateInfo.HtmlFieldPrefix = "Persons.First";
See the following links for details on this:
- http://forums.asp.net/t/1627585.aspx/1
- http://forums.asp.net/t/1624152.aspx
Notice this overload of Html.Partial():
Partial(HtmlHelper, String, Object, ViewDataDictionary)
http://msdn.microsoft.com/en-us/library/ee407417.aspx

How to: .NET MVC2 array of buttons

I have something like this in my View
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/ViewMasterPage.Master"
Inherits="System.Web.Mvc.ViewPage<MVC.ViewModels.EditViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<%
Html.EnableClientValidation();%>
<%
using (Html.BeginForm("Edit", "Edit", FormMethod.Post, new { #class = "myform" }))
{%>
<%for (int i = 0; i < Model.Activity.Count; ++i)
{%>
<div class="editor-field">
<%:Html.DropDownListFor(x => x.Activity[i].SelectedActivity, Model.SelectListActivity)%>
<input class="button" type="submit" value="<%:i%>" name="add_Button[<%:i%>]"/>
</div>
<%}
}
%>
</asp:Content>
Controller:
[HttpPost, Authorize]
public ActionResult Edit(string[] add_Button, FormCollection collection)
When I go to my controller, only the button on index [0] is captured, why is that?
both ICollection<string> add_Button and string[] add_Button did not work for me.
In another word, How do you send array of button like this:
<input class="button" type="submit" value="Add" name="add_Button[0]" id="Submit3" />
<input class="button" type="submit" value="Add" name="add_Button[1]" id="Submit4" />
<input class="button" type="submit" value="Add" name="add_Button[2]" id="Submit5" />
<input class="button" type="submit" value="Add" name="add_Button[3]" id="Submit6" />
<input class="button" type="submit" value="Add" name="add_Button[4]" id="Submit7" />
<input class="button" type="submit" value="Add" name="add_Button[5]" id="Submit8" />
Thank you for your help
Firstly you need to make that DIV a FORM field to contain your inputs.
Secondly, to increment the value of i you need to make it say i++ instead of ++i.
Lastly, if you only want the buttons to repeat, you need to move the for loop around the button, not around the div and dropdownlist.
<% for (int i= 0; i < Model.Activity.Count; i++)
{ %>
<input class="button" type="submit" value="Add" name="button[<%: i.ToString() %>]" id="Submit<%: i.ToString() %>" />
<% } %>
Hope this helps!
Ok....I found something interesting.
My controller
public ActionResult Edit(String[] add_Button, FormCollection collection)
Any button that is clicked other than first one goes to FormCollection.
So If I click add_Button[1], it will actually go to collection["add_Button[1]"]
As promised, here is my answer with your updated source.
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/ViewMasterPage.Master"
Inherits="System.Web.Mvc.ViewPage<MVC.ViewModels.EditViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<%
Html.EnableClientValidation();%>
<% for (int i = 0; i < Model.Activity.Count; i++)
{%>
<% using (Html.BeginForm("Edit", "Edit", FormMethod.Post, new { #class = "myform" }))
{%>
<div class="editor-field">
<%:Html.DropDownListFor(x => x.Activity[i].SelectedActivity, Model.SelectListActivity)%>
<input class="button" type="submit" value="<%: i.ToString() %>" name="add_Button[<%: i.ToString() %>]"/>
</div>
<%}
}
%>
</asp:Content>

Model binding nested collections in ASP.NET MVC

I'm using Steve Sanderson's BeginCollectionItem helper with ASP.NET MVC 2 to model bind a collection if items.
That works fine, as long as the Model of the collection items does not contain another collection.
I have a model like this:
-Product
--Variants
---IncludedAttributes
Whenever I render and model bind the Variants collection, it works jusst fine. But with the IncludedAttributes collection, I cannot use the BeginCollectionItem helper because the id and names value won't honor the id and names value that was produced for it's parent Variant:
<div class="variant">
<input type="hidden" value="bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126" autocomplete="off" name="Variants.index">
<input type="hidden" value="0" name="Variants[bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126].SlotAmount" id="Variants_bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126__SlotAmount">
<table class="included-attributes">
<input type="hidden" value="0" name="Variants.IncludedAttributes[c5989db5-b1e1-485b-b09d-a9e50dd1d2cb].Id" id="Variants_IncludedAttributes_c5989db5-b1e1-485b-b09d-a9e50dd1d2cb__Id" class="attribute-id">
<tr>
<td>
<input type="hidden" value="0" name="Variants.IncludedAttributes[c5989db5-b1e1-485b-b09d-a9e50dd1d2cb].Id" id="Variants_IncludedAttributes_c5989db5-b1e1-485b-b09d-a9e50dd1d2cb__Id" class="attribute-id">
</td>
</tr>
</table>
</div>
If you look at the name of the first hidden field inside the table, it is Variants.IncludedAttributes - where it should have been Variants[bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126].IncludedAttributes[...]...
That is because when I call BeginCollectionItem the second time (On the IncludedAttributes collection) there's given no information about the item index value of it's parent Variant.
My code for rendering a Variant looks like this:
<div class="product-variant round-content-box grid_6" data-id="<%: Model.AttributeType.Id %>">
<h2><%: Model.AttributeType.AttributeTypeName %></h2>
<div class="box-content">
<% using (Html.BeginCollectionItem("Variants")) { %>
<div class="slot-amount">
<label class="inline" for="slotAmountSelectList"><%: Text.amountOfThisVariant %>:</label>
<select id="slotAmountSelectList"><option value="1">1</option><option value="2">2</option></select>
</div>
<div class="add-values">
<label class="inline" for="txtProductAttributeSearch"><%: Text.addVariantItems %>:</label>
<input type="text" id="txtProductAttributeSearch" class="product-attribute-search" /><span><%: Text.or %> <a class="select-from-list-link" href="#select-from-list" data-id="<%: Model.AttributeType.Id %>"><%: Text.selectFromList.ToLowerInvariant() %></a></span>
<div class="clear"></div>
</div>
<%: Html.HiddenFor(m=>m.SlotAmount) %>
<div class="included-attributes">
<table>
<thead>
<tr>
<th><%: Text.name %></th>
<th style="width: 80px;"><%: Text.price %></th>
<th><%: Text.shipping %></th>
<th style="width: 90px;"><%: Text.image %></th>
</tr>
</thead>
<tbody>
<% for (int i = 0; i < Model.IncludedAttributes.Count; i++) { %>
<tr><%: Html.EditorFor(m => m.IncludedAttributes[i]) %></tr>
<% } %>
</tbody>
</table>
</div>
<% } %>
</div>
</div>
And the code for rendering an IncludedAttribute:
<% using (Html.BeginCollectionItem("Variants.IncludedAttributes")) { %>
<td>
<%: Model.AttributeName %>
<%: Html.HiddenFor(m => m.Id, new { #class = "attribute-id" })%>
<%: Html.HiddenFor(m => m.ProductAttributeTypeId) %>
</td>
<td><%: Model.Price.ToCurrencyString() %></td>
<td><%: Html.DropDownListFor(m => m.RequiredShippingTypeId, AppData.GetShippingTypesSelectListItems(Model.RequiredShippingTypeId)) %></td>
<td><%: Model.ImageId %></td>
<% } %>
As you are using MVC 2 and EditorFor, you shouldn't need to use Steve's solution, which I believe is just a work around for MVC 1. You should just be able to do something like:
<% for (int i = 0; i < Model.Variants.Count; i++) { %>
<%= Html.DisplayFor(m => m.Variants[i].AttributeType.AttributeTypeName) %>
<% for (int j = 0; j < Model.Variants[i].IncludedAttributes.Count; j++) { %>
<%= Html.EditorFor(m => m.Variants[i].IncludedAttributes[j]) %>
<% } %>
<% } %>
Please note that the use of the indexes ...[i]...[j]... is important and is how MVC will know how to render the Id's and names correctly.

Return multiple views to one ActionResult with ASP.NET MVC

What I want to achieve essentially is:
Items assigned to me
Item 1 assigned to me
Item 2 assigned to me
Item 3 assigned to me
All open items
Item 1 open to everyone
Item 2 open to everyone
Item 3 open to everyone
Item 4 open to everyone
Though from what I have experienced of MVC so far is that I would have to return the data to the view model to be able to use it in the view itself in the following manner:
<asp:Content ID="ticketsContent" ContentPlaceHolderID="MainContent" runat="server">
<div id="hdMain">
<div id="hdMainTop"><img src="images/hdMainTop.gif" alt="" /></div>
<div id="hdMainContent">
<div id="numberOfCalls">Calls assigned to you (<%=Html.ViewData("MyOpenCallsCount")%>)</div>
<div id="assignedToMe">
<div id="callHeaders">
<table id="callHeadersTbl" cellpadding="0" cellspacing="0">
<tr>
<td width="54"> </td>
<td width="270">Subject</td>
<td width="148">Logged</td>
<td width="120">Updated</td>
</tr>
</table>
</div>
<div id="greyTicketBar"> Assignee: <strong><%=Html.ViewData("UserName")%></strong></div>
<table cellpadding="0" cellspacing="0" width="643">
<% For Each aT In ViewData.Model%>
<tr>
<td width="54" class="ticketList"> </td>
<td width="270" class="ticketList"><%=Html.ActionLink(aT.Title, "Details", New With {.id = aT.CallID})%></td>
<td width="148" class="ticketList"><%=aT.loggedOn.Date.ToShortDateString%></td>
<td width="115" class="ticketList"><%=aT.updatedOn.Date.ToShortDateString%></td>
</tr>
<% Next%>
</table>
</div>
</div>
<div id="hdMainBottom"><img src="images/hdMainBottom.gif" alt="" /></div>
<div id="bigbreak">
<br />
</div>
<div id="hdMainTop"><img src="images/hdMainTop.gif" alt="" /></div>
<div id="hdMainContent">
<div id="numberOfCalls">All unsolved calls (<%=Html.ViewData("OpenCallCount")%>)</div>
<div id="unsolvedTix">
<div id="callHeaders">
<table id="callHeadersTbl" cellpadding="0" cellspacing="0">
<tr>
<td width="54"> </td>
<td width="270">Subject</td>
<td width="148">Logged</td>
<td width="58">Priority</td>
<td width="120">Updated</td>
</tr>
</table>
</div>
<div id="greyTicketBar"></div>
<table cellpadding="0" cellspacing="0" width="643">
<% For Each t As hdCall In ViewData.Model%>
<tr>
<td width="51" class="ticketList" align="center"><img src="/images/icons/<%=t.hdPriority.Priority%>.gif" /></td>
<td width="270" class="ticketList"><%=Html.ActionLink(t.Title, "Details", New With {.id = t.CallID})%></td>
<td width="148" class="ticketList"><%=t.loggedOn%></td>
<td width="58" class="ticketList"><%=t.hdPriority.Priority%></td>
<td width="115" class="ticketList"><%=t.updatedOn%></td>
</tr>
<% Next%>
</table>
</div>
</div>
<div id="hdMainBottom"><img src="images/hdMainBottom.gif" alt="" /></div>
</div>
<div id="hdSpacer"></div>
<div id="hdMenus">
<div id="browseBox">
<div id="blueTop"><img src="images/blueboxTop.gif" /></div>
<div id="blueContent">
<img src="images/browse.gif" alt="Browse" /><br /><br />
<ul>
<li> Calls for Topps<br /><br /></li>
<li> Calls for TCH<br /><br /></li>
</ul>
</div>
<div id="blueBottom"><img src="images/blueboxBottom.gif" /></div>
<br />
<div id="Dashboard">
<div id="blueTop"><img src="images/blueboxTop.gif" /></div>
<div id="blueContent"><img src="images/dashboard.gif" alt="Dashboard" /><br /><br />
<div id="storePercent"><%=Html.ViewData("OpenCallCount")%><br />
Calls Open</div>
<ul style="font-weight: bold;">
<li> Urgent: <%=Html.ViewData("UrgentCallCount")%><br /><br /></li>
<li> High: <%=Html.ViewData("HighCallCount")%><br /><br /></li>
<li> Normal: <%=Html.ViewData("NormalCallCount")%><br /><br /></li>
<li> Low: <%=Html.ViewData("LowCallCount")%></li>
</ul>
</div>
<div id="blueBottom"><img src="images/blueboxBottom.gif" /></div>
</div>
</div>
</asp:Content>
Now, the idea I have for it, even though I know it won't work would basically be:
'
' GET: /Calls/
<Authorize()> _
Function Index() As ActionResult
ViewData("OpenCallCount") = callRepository.CountOpenCalls.Count()
ViewData("UrgentCallCount") = callRepository.CountUrgentCalls.Count()
ViewData("HighCallCount") = callRepository.CountHighCalls.Count()
ViewData("NormalCallCount") = callRepository.CountNormalCalls.Count()
ViewData("LowCallCount") = callRepository.CountLowCalls.Count()
ViewData("MyOpenCallsCount") = callRepository.CountMyOpenCalls(Session("LoggedInUser")).Count()
ViewData("UserName") = Session("LoggedInUser")
Dim viewOpenCalls = callRepository.FindAllOpenCalls()
Dim viewMyOpenCalls = callRepository.FindAllMyCalls(Session("LoggedInUser"))
Return View(viewOpenCalls)
Return View(viewMyOpenCalls)
End Function
What I'm wondering is, what would be the correct way to do this? I haven't a clue as how to go about the right way, I think I at least have the theory there though, just not how to implement it.
Thanks for any help in advance.
EDIT
Based on the below comments, I have made the following code edits/additions:
Class Calls
Private _OpenCalls As hdCall
Public Property OpenCalls() As hdCall
Get
Return _OpenCalls
End Get
Set(ByVal value As hdCall)
_OpenCalls = value
End Set
End Property
Private _MyCalls As hdCall
Public Property MyCalls() As hdCall
Get
Return _MyCalls
End Get
Set(ByVal value As hdCall)
_MyCalls = value
End Set
End Property
End Class
Index() Action
'
' GET: /Calls/
<Authorize()> _
Function Index() As ActionResult
ViewData("OpenCallCount") = callRepository.CountOpenCalls.Count()
ViewData("UrgentCallCount") = callRepository.CountUrgentCalls.Count()
ViewData("HighCallCount") = callRepository.CountHighCalls.Count()
ViewData("NormalCallCount") = callRepository.CountNormalCalls.Count()
ViewData("LowCallCount") = callRepository.CountLowCalls.Count()
ViewData("MyOpenCallsCount") = callRepository.CountMyOpenCalls(Session("LoggedInUser")).Count()
ViewData("UserName") = Session("LoggedInUser")
Dim viewOpenCalls As New Calls With {.OpenCalls = callRepository.FindAllOpenCalls()}
Dim viewMyOpenCalls As New Calls With {.MyCalls = callRepository.FindAllMyCalls(Session("LoggedInUser"))}
Return View(New Calls())
End Function
Calls/Index.aspx
<%# Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Calls>" %>
<%# Import Namespace="CustomerServiceHelpdesk" %>
<asp:Content ID="ticketsHeader" ContentPlaceHolderID="TitleContent" runat="server">
Topps Customer Service Helpdesk - View All Calls
</asp:Content>
<asp:Content ID="ticketsContent" ContentPlaceHolderID="MainContent" runat="server">
<div id="hdMain">
<div id="hdMainTop"><img src="images/hdMainTop.gif" alt="" /></div>
<div id="hdMainContent">
<div id="numberOfCalls">Calls assigned to you (<%=Html.ViewData("MyOpenCallsCount")%>)</div>
<div id="assignedToMe">
<div id="callHeaders">
<table id="callHeadersTbl" cellpadding="0" cellspacing="0">
<tr>
<td width="54"> </td>
<td width="270">Subject</td>
<td width="148">Logged</td>
<td width="120">Updated</td>
</tr>
</table>
</div>
<div id="greyTicketBar"> Assignee: <strong><%=Html.ViewData("UserName")%></strong></div>
<table cellpadding="0" cellspacing="0" width="643">
<% For Each aT In Model.MyCalls%>
<tr>
<td width="54" class="ticketList"> </td>
<td width="270" class="ticketList"><%=Html.ActionLink(aT.Title, "Details", New With {.id = aT.CallID})%></td>
<td width="148" class="ticketList"><%=aT.loggedOn.Date.ToShortDateString%></td>
<td width="115" class="ticketList"><%=aT.updatedOn.Date.ToShortDateString%></td>
</tr>
<% Next%>
</table>
</div>
</div>
<div id="hdMainBottom"><img src="images/hdMainBottom.gif" alt="" /></div>
<div id="bigbreak">
<br />
</div>
<div id="hdMainTop"><img src="images/hdMainTop.gif" alt="" /></div>
<div id="hdMainContent">
<div id="numberOfCalls">All unsolved calls (<%=Html.ViewData("OpenCallCount")%>)</div>
<div id="unsolvedTix">
<div id="callHeaders">
<table id="callHeadersTbl" cellpadding="0" cellspacing="0">
<tr>
<td width="54"> </td>
<td width="270">Subject</td>
<td width="148">Logged</td>
<td width="58">Priority</td>
<td width="120">Updated</td>
</tr>
</table>
</div>
<div id="greyTicketBar"></div>
<table cellpadding="0" cellspacing="0" width="643">
<% For Each t As hdCall In Model.OpenCalls%>
<tr>
<td width="51" class="ticketList" align="center"><img src="/images/icons/<%=t.hdPriority.Priority%>.gif" /></td>
<td width="270" class="ticketList"><%=Html.ActionLink(t.Title, "Details", New With {.id = t.CallID})%></td>
<td width="148" class="ticketList"><%=t.loggedOn%></td>
<td width="58" class="ticketList"><%=t.hdPriority.Priority%></td>
<td width="115" class="ticketList"><%=t.updatedOn%></td>
</tr>
<% Next%>
</table>
</div>
</div>
<div id="hdMainBottom"><img src="images/hdMainBottom.gif" alt="" /></div>
</div>
<div id="hdSpacer"></div>
<div id="hdMenus">
<div id="browseBox">
<div id="blueTop"><img src="images/blueboxTop.gif" /></div>
<div id="blueContent">
<img src="images/browse.gif" alt="Browse" /><br /><br />
<ul>
<li> Calls for Topps<br /><br /></li>
<li> Calls for TCH<br /><br /></li>
</ul>
</div>
<div id="blueBottom"><img src="images/blueboxBottom.gif" /></div>
<br />
<div id="Dashboard">
<div id="blueTop"><img src="images/blueboxTop.gif" /></div>
<div id="blueContent"><img src="images/dashboard.gif" alt="Dashboard" /><br /><br />
<div id="storePercent"><%=Html.ViewData("OpenCallCount")%><br />
Calls Open</div>
<ul style="font-weight: bold;">
<li> Urgent: <%=Html.ViewData("UrgentCallCount")%><br /><br /></li>
<li> High: <%=Html.ViewData("HighCallCount")%><br /><br /></li>
<li> Normal: <%=Html.ViewData("NormalCallCount")%><br /><br /></li>
<li> Low: <%=Html.ViewData("LowCallCount")%></li>
</ul>
</div>
<div id="blueBottom"><img src="images/blueboxBottom.gif" /></div>
</div>
</div>
</asp:Content>
However, the line <%=Html.ViewData("MyOpenCallsCount")%> gives me an End of Statement expected error.
Also, I did get it to compile once, but I got the error Unable to cast object of type 'System.Data.Linq.DataQuery1[CustomerServiceHelpdesk.hdCall]' to type 'CustomerServiceHelpdesk.hdCall'. from the line Dim viewOpenCalls As New Calls With {.OpenCalls = callRepository.FindAllOpenCalls()}
Where did I go wrong?
I'm a bit of noob when it comes to things like this, so any help is much appreciated.
Well, you can't return two values from a function, if that's what you are trying to do (the title suggests that's what you want).
Plus that's not how http works anyway. There's always just one response for a request.
But if you are trying to send both your viewOpenCalls and viewMyOpenCalls objects to one view, then you can do that with making your view have a model that'll hold both of them.
Like this :
//My VB is a bit rusty so I'm writing this in C#
class Calls {
public yourDataType OpenCalls { get; set; }
public yourDataType MyCalls { get; set; }
}
In your controller action :
return View(new Calls { OpenCalls = viewOpenCalls, MyCalls = viewMyOpenCalls })
//I gues in VB it would be like this :
Dim viewOpenCalls = callRepository.FindAllOpenCalls()
Dim viewMyOpenCalls = callRepository.FindAllMyCalls(Session("LoggedInUser"))
Return View(New Calls _
With {.OpenCalls = viewOpenCalls, .MyCalls = viewMyOpenCalls})
In your view make sure it's model is type of the Calls class.
<%# Page Inherits="System.Web.Mvc.ViewPage<Calls>" %>
And now you can access the properties with <%=Model.OpenCalls %> and <%=Model.MyCalls %>
Once I'd worked out the correct way of doing it (a little while a go now) I got it working.
For reference, this is the way it should be done:
Public Class TheCalls
Private _OpenCalls As IQueryable(Of hdCall)
Public Property OpenCalls() As IQueryable(Of hdCall)
Get
Return _OpenCalls
End Get
Set(ByVal value As IQueryable(Of hdCall))
_OpenCalls = value
End Set
End Property
Private _AssignedCalls As IQueryable(Of hdCall)
Public Property AssignedCalls() As IQueryable(Of hdCall)
Get
Return _AssignedCalls
End Get
Set(ByVal value As IQueryable(Of hdCall))
_AssignedCalls = value
End Set
End Property
End Class
1) Create a ViewData class. This is just a POCO class with properties defined for each data item you want to show on the view (e.g. OpenCallCount)
2) Create a strongly typed view that uses this ViewData class.
3) Pass a new instance of your ViewData class, with the properties set, to your view.
This will help you avoid using magic strings everywhere (e.g. ViewData("OpenCallCount") = ... becomes myViewDataClass.OpenCallCount = ...)
You could probably tidy up the view by using two partial view classes, or making it slightly more generic, but it will do the job at the moment.

Resources