I want to save data in database using Form with HttpPost but it is not being saved.
This is my controller (CustomersController)
Route for adding a new customer (basically returns a view with the form):
[Route("customers/new")]
public ActionResult New()
{
var membershipTypes = _context.MembershipTypes.ToList();
var viewModel = new NewCustomerViewModel
{
MembershipTypes = membershipTypes
};
return View(viewModel);
}
Post Method
[HttpPost]
[ValidateAntiForgeryToken]
[Route("customers/create")]
public ActionResult Create(Customer customer)
{
if(!ModelState.IsValid)
{
var viewModel = new NewCustomerViewModel
{
Customer = customer,
MembershipTypes = _context.MembershipTypes.ToList()
};
return View("New", viewModel);
}
if(customer.Id == 0)
_context.Customers.Add(customer);
else
{
var customerInDb = _context.Customers.Single(c => c.Id == customer.Id);
customerInDb.Name = customer.Name;
customerInDb.Birthdate = customer.Birthdate;
customerInDb.MemberShipTypeId = customer.MemberShipTypeId;
customerInDb.IsSubscribedToNewsletter = customer.IsSubscribedToNewsletter;
}
_context.SaveChanges();
return RedirectToAction("Index"); //data is not being saved to db and redirection also does not happen
}
This is the code for View:
@model Vidly.ViewModels.NewCustomerViewModel
@{ViewBag.Title = "New";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>New Customer</h2>
@using(@Html.BeginForm("Create", "Customers"))
{
<div class="form-group">
@Html.LabelFor(m => m.Customer.Name)
@Html.TextBoxFor(m => m.Customer.Name ,new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Customer.Name)
</div>
<div class="form-group">
@Html.LabelFor(m => m.Customer.Birthdate)
@Html.TextBoxFor(m => m.Customer.Birthdate, "{0:d MMM yyyy}", new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Customer.Birthdate)
</div>
<div class="checkbox">
<label>
@Html.CheckBoxFor(m => m.Customer.IsSubscribedToNewsletter) Subscribed To Newsletter?
</label>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Customer.MemberShipTypeId)
@Html.DropDownListFor(m => m.Customer.MemberShipTypeId, new SelectList(Model.MembershipTypes, "Id", "Name"), "Select Membership Type" ,new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Customer.MemberShipTypeId)
</div>
@Html.HiddenFor(m => m.Customer.Id);
@Html.AntiForgeryToken()
<button type="submit" class="btn btn-primary">
Submit
</button>
}
I inspected the network Tab while submitting the form and request is being made and data is also being sent but customer.Id is not set to anything and I think that’s the error but don’t know how to resolve it. Here’s the picture for reference:
I don’t know how to solve this as I don’t understand why this is happening. I have an Edit action too and it works fine and updates the data in database but create is not working.
PS: I know there are a few similar worded questions but they don’t solve my problem so please don’t mark this as duplicate.
2
Answers
It doesn’t work because you are passing complex type model from view to controller. In this case you must specify in controller how to process this request. Try to inspect your form html output and you will notice that every property for example: m.Customer.MemberShipTypeId is rendered as Customer_MemberShipTypeId etc.
To fix this change your method to bind each prefix of you complex model. Example:
try also change this
your action should have the same input parameter as your form model
you can also create hidden field for customerId but it doesn’t make much sense for create, since it will always be 0