Neil
Neil

Reputation: 412

MVC, Saving Data into 2 or more Related models from a single Form / View .?

My Model: (i) For Transaction

public class Transaction
{
    [Key]
    public int TransactionId { get; set; }

    public DateTime OnWardDate { get; set; }

    public DateTime ReturnDate { get; set; }

    public virtual UserProfile User { get; set; }


}

(ii) For User

public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    public string UserName { get; set; }

    private UserDetails _details = new UserDetails();
    public virtual UserDetails details
    {
        get { return _details; }
    }
}

(ii) For UserDetails

 public class UserDetails
{
    [Key]
    public int DetailsId { get; set; }

    public string DLNum { get; set; }

}

My Controller for Create Transaction:

    // GET: /Transaction/Create

    public ActionResult Create()
    {
        return View();
    }

    //
    // POST: /Transaction/Create

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Transaction transaction)
    {
        if (ModelState.IsValid)
        {
            db.Transactions.Add(transaction);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(transaction);
    }

My View for Create transaction:

 <div class="editor-label">
        @Html.LabelFor(model => model.OnWardDate)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.OnWardDate)
        @Html.ValidationMessageFor(model => model.OnWardDate)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.User.details.DLNum)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.User.details.DLNum)
        @Html.ValidationMessageFor(model => model.User.details.DLNum)
    </div>

When I Submit the form... model.OnWardDate is getting saved but model.User.details.DLNum is not saving
I hv seen about ViewModel. Is that the only option to go with it? Thanks In Advance.

Upvotes: 1

Views: 900

Answers (2)

terryt
terryt

Reputation: 561

  1. The main issue is that Entity Framework requires both getter and setter for the POCO properties your class UserDetails only has a getter defined for the details property.

Your models could then be:

public class Transaction
{
    [Key]
    public int TransactionId { get; set; }

    public DateTime OnWardDate { get; set; }

    public DateTime ReturnDate { get; set; }

    public virtual UserProfile User { get; set; }

}

public class UserProfile
{
    [Key]
    public int UserId { get; set; }

    public string UserName { get; set; }

    public virtual UserDetails Details { get; set; }
}
public class UserDetails
{
    [Key]
    public int DetailsId { get; set; }

    public string DLNum { get; set; }
}

2. I recommend using the pattern of instantiating the model in the Controller and passing it to the view as in:

    public ActionResult Create()
    {
        var transaction = new Transaction
        {
            User = new UserProfile
            {
                Details = new UserDetails()
            }
        };
        return View(transaction);
    }

This ensures your model is properly constructed and allows you to initialize any properties before the view is rendered. You can often get away shortcutting this, IMHO it is better to be explicit.

Upvotes: 0

valentin
valentin

Reputation: 667

In your case, I would think it's because your setter is private for UserDetails:

public virtual UserDetails details
{
    get { return _details; }
}

If you're creating the tables based on those models and therefore can't afford to modify them, I would indeed advise to make a view model, post using that and then create / update the database entry accordingly.

Upvotes: 1

Related Questions