fcdimitr
fcdimitr

Reputation: 528

MVC ASP.NET Creating two models that are associated in a single view

I am using ASP.NET and I have two models, Contact and Customer and there is a one to one relationship between the two. So, every contact will be added in the contacts entity and when a contact is a customer, the extra information will be added in the customer entity.

I created a ViewModel containing both. When the view model is then passed in the post request, i add first the contact, which adds correctly and then I want to add the customer with relationship to the previous contact, but I don't know how to do it.

[HttpPost]
public ActionResult CustomerCreate(CustomerViewModel customerViewModel)
{
    if (ModelState.IsValid)
    {
        try
        {
            using (var db = new ModelContactContainer())
            {
                db.Contact.Add(customerViewModel.contact);
                customerViewModel.customer.Contact = customerViewModel.contact;
                db.Customer.Add(customerViewModel.customer);
                db.SaveChanges();
            }
            return RedirectToAction("Index");
        }
        catch
        {
            return CustomerCreate();
        }
    }
    return CustomerCreate();
}

UPDATE

These are the classes for my models:

Contact.cs

using System;
using System.Collections.Generic;
public partial class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Customer Customer { get; set; }
}

Customer.cs

using System;
using System.Collections.Generic;

using System.ComponentModel.DataAnnotations;

public partial class Customer
{
    public int Id { get; set; }
    public string Something { get; set; }

    [Required]
    public virtual Contact Contact { get; set; }
}

CustomerViewModel.cs

public class CustomerViewModel
    {
        public Contact contact { get; set; }
        public Customer customer { get; set; }
    }

And here is the view

CustomerCreate.cshtml

@model W3SchoolsApplication.Models.CustomerViewModel
@{
    ViewBag.Title = "Create Customer";
}

<h2>@ViewBag.Title</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.contact.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.contact.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.contact.Name, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.customer.Something, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.customer.Something, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.customer.Something, "", new { @class = "text-danger" })
            </div>

        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

Upvotes: 0

Views: 656

Answers (2)

Radu Porumb
Radu Porumb

Reputation: 785

You have to understand what happens behind the scenes to understand why this doesn't work.

using (var db = new ModelContactContainer())
{
    db.Contact.Add(customerViewModel.contact);
    db.SaveChanges(); // so the above has an ID and the foreign key relationship works

    // this doesn't add anything to the database, it just populates the foreign key relationship
    customerViewModel.customer.Contact = customerViewModel.contact; 
    db.Customer.Add(customerViewModel.customer);
    db.SaveChanges();
}

If you want this entire operation to be atomic you'll have to wrap it in a transaction, like so:

using (var db = new ModelContactContainer())
using (var transaction = db.Database.BeginTransaction())
{
    db.Contact.Add(customerViewModel.contact);
    db.SaveChanges();

    customerViewModel.customer.Contact = customerViewModel.contact; 
    db.Customer.Add(customerViewModel.customer);
    db.SaveChanges();

    transaction.Commit();
}

Upvotes: 2

bunny1985
bunny1985

Reputation: 772

I'm not sure but maybe you should change the order and you probably don't have to add contact explicit:

        customerViewModel.customer.Contact = customerViewModel.contact;
        db.Contact.Add(customerViewModel.customer);
        db.SaveChanges();

Upvotes: 0

Related Questions