I am trying to create a simple form in ASP.MVC which shows a list of quotes, and allows the user to create work orders by selecting a person from a drop down list to assign that quote to, and then submitting the form all in one go.
My problem is that my use of DropDownListFor within a foreach loop is causing an error and I don't think I'm going about this the right way.
A (somewhat simplified) quote looks like this:
public class QuoteItem
{
public QuoteItem()
{
this.IsWorkOrder = false;
}
[Key]
public int QuoteItemCostID { get; set; }
public string Item { get; set; }
public decimal? Subtotal { get; set; }
public bool IsWorkOrder { get; set; }
[NotMapped]
public string AssignedTo { get; set; }
}
I have a View Model configured as follows:
public class UnassignedWorkOrdersViewModel
{
public IEnumerable<QuoteItemCost> QuoteItemCosts { get; set; }
public IEnumerable<SelectListItem> Trades { get; set; }
}
And a controller action that looks like this:
public ActionResult Unassigned(int id = 0)
{
var trades = db.UserProfiles.Where(u => u.Typpe == "Trade").ToArray().Select(x => new SelectListItem
{
Value = x.FirstName + " " + x.LastName,
Text = x.FirstName + " " + x.LastName
}).ToList();
var quoteItems = db.QuoteItems
.Where(x => x.IsWorkOrder == false)
.ToList();
UnassignedWorkOrdersViewModel viewModel = new UnassignedWorkOrdersViewModel
{
Trades = trades,
QuoteItemCosts = quoteItemCosts
};
return View(viewModel);
}
My problem is that in my view, I'm trying to show each work order and the drop down list of trades next to it, and the way that I thought I'd do it is to map the class property "AssignedTo" to the value in the drop down list, however this doesn't work, as the DropDownList expects a LINQ expression as the first parameter:
@model Project.ViewModels.UnassignedWorkOrdersViewModel
@if (Model.QuoteItemCosts.Any())
{
using (Html.BeginForm("Unassigned", "WorkOrder", FormMethod.Post, null))
{
@Html.AntiForgeryToken()
<table>
@foreach (var item in Model.QuoteItemCosts)
{
<tr>
<td style="width:100px;">
<b>Item:</b> @item.Item
</td>
<td style="width:200px;">
<b>Total:</b> @item.Subtotal
</td>
<td>
<b>Assign:</b>
@Html.DropDownListFor(
item.AssignedTo, // THIS LINE CAUSES AN ERROR
Model.Trades,
"", new { @id = "ddlStatus", @style = "width:100%" })
</td>
</tr>
}
</table>
}
How can I resolve this and am I even going about this the right way? On form submit, I should expect to get back the ViewModel which would then return all my QuoteItems, but with an AssignedTo entry if the user has selected a person from the drop down list.
Edit:
Andrei's suggestion below has helped and led me to another solution where my DropDownListFor now looks like this:
@Html.DropDownListFor(
m => m.QuoteItemCosts.First(q => q.QuoteItemCostID == item.QuoteItemCostID).AssignedTo,
Model.Trades,
"", new { @id = "ddlStatus", @style = "width:100%" })
but when I submit the form the viewmodel is null:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Unassigned(UnassignedWorkOrdersViewModel viewModel)
{
// My viewModel is null
return RedirectToAction("Index");
}
I've updated my razor code to include a Html.BeginForm as well.