ASP.NET MVC: How to use multiple models in one Vie

2019-07-31 19:29发布

I have the following ViewModel that includes 2 other models:

public class ViewModel
{
   public ViewModel1 viewModel1 { get; set; }
   public ViewModel2 viewModel2 { get; set; }
}

My View looks like this:

@Html.TextBoxFor(m => m.viewModel1.NameOfCustomer)
@Html.TextBoxFor(m => m.viewModel2.ProductCategory)

And finally the controller:

public ActionResult CreateNewOrder(ViewModel viewModel)
{

  Model1 myModel1 = new Model1()
  {
    NameOfCustomer = viewModel.viewModel1.NameOfCustomer
  };

  db.Orders.Add(myModel1);
  db.SaveChanges();

  return View(viewModel);
}

The problem is, if I want to take the data from my ViewModel to pass it to my actual model, it does not work. It just shows null as value. If I do the following change to my controller data is there but this does not work as it should:

public ActionResult CreateNewOrder(ViewModel viewModel)
{
  // that works
  viewModel.viewModel1.NameOfCustomer = "John John";

  Model1 myModel1 = new Model1()
  {
    myModel1.NameOfCustomer = viewModel.viewModel1.NameOfCustomer
  };

  db.Orders.Add(myModel1);
  db.SaveChanges();

  return View(viewModel);
}

So I guess the problem is, my data from my view is not being send correctly to my ViewModel. I hope you guys can give me a hint what Im doing wrong.

Regards,

2条回答
SAY GOODBYE
2楼-- · 2019-07-31 19:42

Edited following @Stephen Muecke's comment, doesn't sound like this is the case. However, I'll leave this answer here, as my first port of call would still be to check out the POST payload in the request to make sure it was going across the wire as expected, so this part may be useful


It looks like it's because the data coming into your MVC action, is essentially a flattened view model, whereas the model expected in the action is hierarchical.

If look at the network tab within your browser's dev tools, find the POST request being made, and check the payload being sent to the server.

Sounds like this is being posted:
{"NameOfCustomer": "SomePerson", ....}

Which won't be autobinding server-side to your model, because ViewModel does not itself have a NameOfCustomer property - instead, it's on a child object held in the viewModel1 property. So, autobinding would work if the following was being posted:
{"viewModel1": {"NameOfCustomer" : "SomePerson", ....}}

Solutions include:
1) construct the payload to post from JS yourself, ensuring the structure reflects the nested objects correctly as above
2) Create a flattened viewmodel, so all properties from ViewModel1 are held directly at top level in the ViewModel class
3) Create a custom model binder

查看更多
Luminary・发光体
3楼-- · 2019-07-31 19:59

Your code should properly carry the information to the controller(see a similar fiddle here)

The piece:

Model1 myModel1 = new Model1()
  {
    NameOfCustomer = viewModel.viewModel1.NameOfCustomer
  };

  db.Orders.Add(myModel1);
  db.SaveChanges();

Are you sure you are doing the right thing here? You are creating a Model1 type variable and add it to the Orders in your database. Are you getting any errors? Maybe the right code should be something like:

      Order myModel1 = new Order ()
      {
        NameOfCustomer = viewModel.viewModel1.NameOfCustomer
      };

      db.Orders.Add(myModel1);
      db.SaveChanges();
查看更多
登录 后发表回答