1

I have the following code, with an existing customer. I need to create a form that created an Order, and pass it to my Controller.

I tried changing my model type on that page to Order instead of Customer, but then I'm gonna have to pass the Order object as well, or at least the OrderId.

Models

public class Customer
{
   public int Id { set; get; }
   public string FirstName { set; get; }
   public string LastName { set; get; }
   public List<Order> Orders { get; set;}
}

public class Order
{
   public int Id { set; get; }
   public string ItemName { set; get; }
   public DateTime SomeDate { set; get; }
}

Controller

public class OrderController : Controller
{
   [HttpPost]
   public Create ActionResult(Customer customer)
   {
      // Customer doesn't have the values that it suppose to have
      // All fields including the array of orders are null
      customerStorage.UpdateOrders(customer);

      return ("ItemListPartial", customer.orders);
   }
}

View

@model Company.Application.Model.Customer;

@using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
    // How can I bind this to Order object ?
    // I can't define model as Order, because then I need to pass Customer Separately
    @Html.TextBoxFor(o => o.Orders[0].ItemName)
    @Html.TextBoxFor(o => o.Orders[0].SomeDate)
    <input type="submit" value="Add" />
}
4
  • If you are creating an order, your object should be an Order. Is the problem that you are wanting to associate it with a customer? Not sure why you aren't using an Order object for your binding. Commented Mar 11, 2013 at 1:17
  • public ActionResult(Customer customer) is this a typo ? missing function name. Commented Mar 11, 2013 at 1:18
  • @Ravi Thanks, it was a type fixed it. Commented Mar 11, 2013 at 1:30
  • @MikeC. The problem is if order doesn't know anything about The customer, and I don't want to add a customer id to order, so if I switch the method to expect an Order how would I know what customer this order belongs to? Trying to avoid hacky code, and not pass the customer id separately Commented Mar 11, 2013 at 1:31

2 Answers 2

1

I suppose you're looking for what this blog article describes: ASP.NET MVC Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

Quote from the blog:

If the signature looks like this:

public ActionResult Blah(IDictionary<string, Company> stocks) {
  // ...
}

And we are given this in HTML:

<input type="text" name="stocks[0].Key" value="MSFT" />
<input type="text" name="stocks[0].Value.CompanyName" value="Microsoft Corporation" />
<input type="text" name="stocks[0].Value.Industry" value="Computer Software" />
<input type="text" name="stocks[1].Key" value="AAPL" />
<input type="text" name="stocks[1].Value.CompanyName" value="Apple, Inc." />
<input type="text" name="stocks[1].Value.Industry" value="Consumer Devices" />

Which like this:

stocks[0].Key = "MSFT"
stocks[0].Value.CompanyName = "Microsoft Corporation"
stocks[0].Value.Industry = "Computer Software"
stocks[1].Key = "AAPL"
stocks[1].Value.CompanyName = "Apple, Inc."
stocks[1].Value.Industry = "Consumer Devices"

Then it will be just as if we had written:

stocks = new Dictionary<string, Company>() {
  { "MSFT", new Company() { CompanyName = "Microsoft Corporation", Industry = "Computer Software" } },
  { "AAPL", new Company() { CompanyName = "Apple, Inc.", Industry = "Consumer Devices" } }
};
Sign up to request clarification or add additional context in comments.

Comments

0

This IMO is how you should be handling this:

Pass customerID in your viewbag if you're really not wanting to make a viewmodel (p.s. It is ok to make a viewmodel!)

public class OrderController : Controller
{
   public ActionResult Create(int customerID)
   {
      ViewBag.CustomerID = customerID
      Order ord = new Order(o);
      return View(ord);
   }
}

your post method:

[HttpPost]
public ActionResult Create(int CustomerID, Order order)
{
  //create your order
}

your cshtml

@model Company.Application.Model.Order;

@using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
    @Html.TextBoxFor(o => o.ItemName)
    @Html.TextBoxFor(o => o.SomeDate)
    @Html.Hidden("CustomerID",ViewBag.CustomerID)
    <input type="submit" value="Add" />
}

3 Comments

Why can't use just make a new model class that has both a Customer property and an Order property (and whatever else you need). That way you can have both and tie them together more easily. You are not confined to just models that match your database. I do this all the time.
I usually make a viewmodel for all my models, and I do mention it, but the OP didn't seem to want to do that, so I just commented about it. Also, I think passing up to two items through ViewBag is acceptable. If it were 3 or more I'd probably more strongly recommend a viewmodel than I have here, definately.
Indeed, even though ViewModel adds an extra layer, in my experience, for complex applications, it is worth the effort. I've been using ViewModel pattern along with AutoMapper, and it has been really great so far.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.