ASP.NET MVC Creating an object with related object

2020-03-30 05:05发布

问题:

I'm new to ASP.NET MVC and I want to create a view where I can create a new object along with the related objects.

As example: I have the following class Person:

public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public virtual List<Address> Addresses { get; set; }
}

And the class Address:

public class Address
{
    public int AddressId { get; set; }
    public string City { get; set; }
    public string Street { get; set; }

    public int PersonId { get; set; }
    public virtual Person Person { get; set; }
}

What I want to achieve is having a view where the user can type in the data for the person and any number of addresses for this user.

My first (simple) attempt was simply providing an action link which is mapped to a controller method. This method takes a Person object as a parameter, adds a Address object to the collection Addresses and returns a new create view (maybe not nice, but this worked). But when I tried to add a second address I noticed that the Person's collection of addresses was empty again.

Any sugesstions/best practices for this kind of problem?

Thanks!

回答1:

I would suggest you the following approach:

1.Create a view models:

public class AddressViewModel
{ 
    public string City { get; set; }
    public string Street { get; set; }
}

public class PersonViewModel()
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public AddressViewModel AddressViewModelTemplate {get; set;}
    public Collection<AddressViewModel> Addresses {get; set;}
}

Then in your view you can use hidden EditorTempalete for the AddressViewModelTemplate , and show it with javascript on some button click. Of course, you will have to adjust the names of the generated collection for the binding.

Sample Editor Template. You can choose better structure.

    @model AddressViewModel
    <div>
        <div>@Html.LabelFor(x => x.City)</div>
        <div>@Html.TextBoxFor(x => x.City)</div>
    </div>
    <div>
        <div>@Html.LabelFor(x => x.Street)</div>
        <div>@Html.TextBoxFor(x => x.Street)</div>
    </div>

The in your strongly typed View:

@model PersonViewModel;
@using(Html.BeginForm())
{
    //Display textbox for Person properties here
    ....
    <div id="addressInfo" style:"dislpay:none">
        @Html.EditorFor(x => x.AddressViewModelTemplate)
    </div>
    ....
    <div id="AddressesWraper">
        <input id="btnAddAddress" type="button" value="Add new Address" />
    <div>
}
<script>
    $(document).ready(function(){
        $("#btnAddAddress").click(function(){
            $("#AddressesWraper").append("#addressInfo").html();
            refreshAddressNames();
        });
    });
    function refreshAddressNames(){
        /*Here you should name your addresses like this:
          name="AddressViewModel.Addresses[0].City"
          name="AddressViewModel.Addresses[0].Street"
          name="AddressViewModel.Addresses[1].City"
          name="AddressViewModel.Addresses[1].Street"
          ................................[2].City"
                                          [2].Street"

        If you want delete option, you have to mind that too and reorder the collection propely*/
    }
</script>