my model looks like this:
Bank Other LawFirm | | | BankContact OtherContact LawFirmContact |______________|________________| | | Contact
So when creating a contact I am trying to pass the information to create entry for the specific associated entity. At the moment I pass through a RelationId and ContactId and then try and create a the new entity in the controller but my "Save button on the form is not firing. I think it could be because I am not binding the information properly. I'm also posting this to see if this is the correct way to deal with a situation like this
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(ContactFormViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View("ContactForm", viewModel);
}
if (viewModel.Contact.Id == 0)
{
_context.Contacts.Add(viewModel.Contact);
if (viewModel.IsBank)
{
var bankContact = new BankContact()
{
BankId = viewModel.RelationId,
Bank = _context.Banks.Single(b => b.Id == viewModel.RelationId),
ContactId = viewModel.ContactId,
Contact = viewModel.Contact
};
_context.BankContacts.Add(bankContact);
}
else if (viewModel.IsLawFirm)
{
var lawFirmContact = new LawFirmContact()
{
LawFirmId = viewModel.RelationId,
LawFirm = _context.LawFirms.Single(l => l.Id == viewModel.RelationId),
ContactId = viewModel.ContactId,
Contact = viewModel.Contact,
};
_context.LawFirmContacts.Add(lawFirmContact);
}
else if (viewModel.IsOther)
{
var standaloneContact = new StandaloneContact()
{
StandAloneId = viewModel.RelationId,
Standalone = _context.Standalones.Single(s => s.Id == viewModel.RelationId),
Contact = viewModel.Contact,
ContactId = viewModel.ContactId
};
_context.StandaloneContacts.Add(standaloneContact);
}
}
else
{
var contactInDb = _context.Contacts.Single(c => c.Id == viewModel.Contact.Id);
contactInDb.Firstname = viewModel.Contact.Firstname;
contactInDb.Surname = viewModel.Contact.Surname;
contactInDb.Email = viewModel.Contact.Email;
contactInDb.ContactNo = viewModel.Contact.ContactNo;
if (!String.IsNullOrWhiteSpace(viewModel.Contact.AltContactNo))
contactInDb.AltContactNo = viewModel.Contact.AltContactNo;
}
_context.SaveChanges();
return RedirectToAction("Index", "Contacts");
}
<div class="card">
<div class="card-body">
@using (Html.BeginForm("Save", "Contacts"))
{
<div class="form-row">
<div class="col-3">
<div class="form-group">
@Html.LabelFor(c => c.Contact.Firstname, new { @class = "form-control-label" })
@Html.TextBoxFor(c => c.Contact.Firstname, new { @class = "form-control" })
@Html.ValidationMessageFor(c => c.Contact.Firstname)
</div>
</div>
<div class="col-3">
<div class="form-group">
@Html.LabelFor(c => c.Contact.Surname, new { @class = "form-control-label" })
@Html.TextBoxFor(c => c.Contact.Surname, new { @class = "form-control" })
@Html.ValidationMessageFor(c => c.Contact.Surname)
</div>
</div>
</div>
<div class="form-row">
<div class="col-3">
<div class="form-group">
@Html.LabelFor(c => c.Contact.Email, new { @class = "form-control-label" })
@Html.TextBoxFor(c => c.Contact.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(c => c.Contact.Email)
</div>
</div>
<div class="col-3">
<div class="form-group">
@Html.LabelFor(c => c.Contact.Birthday, new { @class = "form-control-label" })
@Html.TextBoxFor(c => c.Contact.Birthday, new { @class = "form-control datepicker-here", @data_language = "en", @autocomplete = "off" })
</div>
</div>
</div>
<div class="form-row">
<div class="col-3">
<div class="form-group">
@Html.LabelFor(c => c.Contact.ContactNo, new { @class = "form-control-label" })
@Html.TextBoxFor(c => c.Contact.ContactNo, new { @class = "form-control" })
@Html.ValidationMessageFor(c => c.Contact.ContactNo)
</div>
</div>
<div class="col-3">
<div class="form-group">
@Html.LabelFor(c => c.Contact.AltContactNo, new { @class = "form-control-label" })
@Html.TextBoxFor(c => c.Contact.AltContactNo, new { @class = "form-control" })
</div>
</div>
</div>
<div class="form-row">
<div class="col-4">
<div class="form-group">
<input type="radio" name="choice-contact-type" id="choice-contact-type-bank" required>
<label for="choice-contact-type-bank">Bank</label>
<div class="reveal-if-active">
@Html.DropDownListFor(b => b.BankContact.BankId, new SelectList(Model.Banks, "Id", "Name "), "", new { @class = "form-control" })
@{Model.IsBank = true;}
</div>
</div>
</div>
<div class="col-4">
<div class="form-group">
<input type="radio" name="choice-contact-type" id="choice-contact-type-lawFirm">
<label for="choice-contact-type-lawFirm">Law Firm</label>
<div class="reveal-if-active">
@Html.DropDownListFor(l => l.LawFirmContact.Id, new SelectList(Model.LawFirms, "Id", "Name"), "", new { @class = "form-control" })
@{Model.IsLawFirm = true;}
</div>
</div>
</div>
<div class="col-4">
<div class="form-group">
<input type="radio" name="choice-contact-type" id="choice-contact-type-standalone">
<label for="choice-contact-type-standalone">Other</label>
<div class="reveal-if-active">
@Html.DropDownListFor(s => s.StandaloneContact.Id, new SelectList(Model.Standalones, "Id", "Name"), "", new { @class = "form-control" })
@{Model.IsOther = true;}
</div>
</div>
</div>
</div>
@Html.AntiForgeryToken()
<button type="submit" class="btn btn-primary">Save</button>
}
</div>
</div>
The hidden dropdown fields are required and therefore validation is not allowing it to go through and because they were hidden I could not see that! The field is required because under my StandaloneContact Id is required. It is always required, so how would I get around this? setting it to a default value?
I'd still like to know if this is the best way to link a model to 3 different models with a many-to-many relationship. Is there another way to do this in MVC?
Try adding this to the form
@using (Html.BeginForm("Save", "Contacts", FormMethod.Post))
Also in regards to the correct way to send data from the view to the controller, it's mostly just what you need at the given time. If you simply want to send data in a form, this is probably the best way. However, if you, for example, what to send this data and then refresh a certain aspect of the page such as a partial view, I would suggest using ajax.
EDIT: Based on the edit to the question, by making the Standalone Contact ID a nullable, this should resolve the issue of the id always being required