Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC - Create object and related objects in one go

I want to create a parent object with child/related objects in the same view. An example would be: create one Father (with some name) along with all his sons (with their names). I have created a view model:

public class FatherViewModel {
  public Father father {get; set;} // has 1 property Name
  public List<Son> {get; set;} // has 1 property Name
}

My question is, how do I get the list of Sons back from the view when the post is performed? I have tried using HiddenFor for each Son id, but no matter what, the list is empty when returned to the controller.

UPDATE:

I tried the Editor Template example by Shyju described below, but my editor is never called. I have 1 object:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? FatherId { get; set; }
    public virtual ICollection<Person> Children { get; set; }
}

I did this:

  1. Scaffolded a full controller for Person with index, create, edit...
  2. Created EditorTemplates folder in Views->Person
  3. Created Person.cshtml:

    @model TestEditorTemplate.Models.Person <div> <h4>Child</h4> @Html.TextBoxFor(s => s.Name) @Html.HiddenFor(s => s.Id) </div>

  4. Added @Html.EditorFor(m => m.Children) to Create.cshtml

Questions:

  1. How can @Html.EditorFor(m => m.Children)possibly work with the editor template when m.Children is a collection of Person and not a single Person?
  2. I want to create (not edit) a father including children at the same time. That means that I have no Ids to pass to the Create view to start with. How can this work? From the example by Shyju, the Ids are already created beforehand?? Or did I just misunderstand the example?
like image 616
Chuckels5584 Avatar asked Aug 18 '14 13:08

Chuckels5584


People also ask

What is a business object in MVC?

Business objects contain both state (data) and behavior, which is the logic of being specific to the business. In MVC, there are several conventions to be followed. Example- Controllers need to have a word controller in them and should implement IController interface either directly or indirectly.

How do I pass objects from the controller to the view?

Using ViewData, we can pass any object from the controller to the view. The Type Conversion code is required when enumerating in the view. For the preceding example, we need to create ViewData to pass a list of teachers and students from the controller to the view.

Can We pass multiple models in a single view in MVC?

This article provides a workaround for multiple models in a single view in MVC. In MVC we cannot pass multiple models from a controller to the single view. This article provides a workaround for multiple models in a single view in MVC.

How to create more objects in Salesforce?

If we want to see more objects, we only need to create more objects using the following command. Suppose our Product model has four fields. These four fields must pass in the create () method to create a new object.


1 Answers

You can use EditorTemplates to handle this. Here is a working sample.

So i have a viewmodel to represent the father-child relationship

public class PersonVM
{
    public int Id { set; get; }
    public string Name { set; get; }
    public int? ParentId { set; get; }
    public List<PersonVM> Childs { set; get; }
}

And in my GET action method, i create an object of my view model and load the Father -childs data to it.

public ActionResult EditorTmp(int id = 1)
{
    //Hard coded for demo, you may replace with actual DB values
    var person = new PersonVM {Id = 1, Name = "Mike"};
    person.Childs = new List<PersonVM>
    {
        new PersonVM {Id = 2, Name = "Scott", ParentId = 11},
        new PersonVM {Id = 2, Name = "Gavin", ParentId = 12}
    };
    return View(person);
}

Now i will create an EditorTemplate. To do that, Go to your Views folder, and Create a directory called EditorTemplates under the directory which has same name as the controller, and add a view with name PersonVM.cshtml

enter image description here

Now, go to this view and add the below code.

@model ReplaceWithYourNameSpaceNameHere.PersonVM
<div>
    <h4>Childs </h4>
    @Html.TextBoxFor(s => s.Name)
    @Html.HiddenFor(s => s.Id)
</div>

Now let's go back to our main view. We need to make this view strongly typed to our original PersonVM. We will use the EditorFor html helper method in this view to call our editor template

@model ReplaceWithYourNameSpaceNameHere.PersonVM
@using (Html.BeginForm())
{
    <div>
        @Html.TextBoxFor(s => s.Name)
        @Html.HiddenFor(s => s.Id)
    </div>
    @Html.EditorFor(s=>s.Childs)
   <input type="submit"/>
}

Now have an HttpPost method in the controller to handle the form posting

[HttpPost]
public ActionResult EditorTmp(PersonVM model)
{
    int fatherId = model.Id;
    foreach (var person in model.Childs)
    {
        var id=person.Id;
        var name = person.Name;
    }
    // to do  : Save ,then Redirect (PRG pattern)
    return View(model);
}

Now, If you put a break point in your HttpPost action method, you can see the Id's of childs are passed to this action method.

enter image description here

One important thing to remember is, Your Editor Template view's name should be same as the type you are binding to it.

like image 113
Shyju Avatar answered Sep 28 '22 06:09

Shyju