action method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterViewModel blahblah)
{
HttpPostedFileBase uploadFile;
if (ModelState.IsValid)
{
if (blahblah != null)
{
var obj = new tblPersonalDetail()
{
FirstName = blahblah.FirstName,
LastName = blahblah.LastName,
Title = blahblah.Title,
Address = blahblah.Address,
Suburb = blahblah.Suburb,
HomePhone = blahblah.HomePhone,
Mobile = blahblah.Mobile,
Email = blahblah.Email,
EmergencyName = blahblah.EmergencyContactName,
EmergencyPhone = blahblah.EmergencyContactPhone,
EmergencyEmail = blahblah.EmergencyContactEmail,
EmergencyRelation = blahblah.EmergencyContactRelation,
DrivingLicenceExpiryDate = blahblah.DrivingLicenceExpiryDate,
DrivingLicenceNo = blahblah.DrivingLicenceNo,
DateofBirth = blahblah.DateofBirth
};
//if (uploadFile != null && !string.IsNullOrEmpty(uploadFile.FileName))
//{
// uploadFile.SaveAs(Server.MapPath($#"~\Content\Images\{uploadFile.FileName}"));
// obj.ScannedImageLocation = ($#"~\Content\Images\{uploadFile.FileName}");
//}
db.tblPersonalDetails.Add(obj);
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(blahblah);
}
--registerviewmodel
public class RegisterViewModel
{
public string Title;
public string FirstName;
public string LastName;
public string Address;
public string Suburb;
public string HomePhone;
public string Mobile;
public string Email;
public string EmergencyContactName;
public string EmergencyContactRelation;
public string EmergencyContactPhone;
public string EmergencyContactEmail;
public string DrivingLicenceNo;
// [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime DrivingLicenceExpiryDate;
public string DrivingLicenceImage;
// [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString ="{0:yyyy-MM-dd}")]
public DateTime DateofBirth;
public string Notes;
public string NextAppointment;
public string Name
{
get
{
return $"{FirstName} {LastName}";
}
}
}
the viewmodel on post is all null. if i use the tblPersonalDetail model class generated by the entityframework and then change the reference in the view (Register.cshtml), it posts with the data. However not with the custom view model.
--Register.cshtml
#model Leo.ViewModel.RegisterViewModel
#{
ViewBag.Title = "Register New User";
}
#using (Html.BeginForm("Register", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-8">
<div class="panel">
<div class="panel-heading tabbable" tabindex="0"><h1>Personal Details</h1></div>
<div class="panel-body">
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.Title, "Title", htmlAttributes: new { #class = "control-label" })
<select class="form-control" id="Title">
<option>Mr</option>
<option>Mrs</option>
<option>Dr</option>
<option>Miss</option>
</select>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.FirstName, "First Name", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-sm-6">
#Html.LabelFor(model => model.LastName, "Last Name", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.Address, "Address", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Address, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-sm-6">
#Html.LabelFor(model => model.Suburb, "Suburb", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Suburb, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.HomePhone, "Home Phone", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.HomePhone, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-sm-6">
#Html.LabelFor(model => model.Mobile, "Mobile", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Mobile, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.Email, "Email", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
</div>
<div class="panel-heading tabbable" tabindex="0"><h1>Emergency Details</h1></div>
<div class="panel-body">
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.EmergencyContactName, "Name", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.EmergencyContactName, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-sm-6">
#Html.LabelFor(model => model.EmergencyContactRelation, "Relation", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.EmergencyContactRelation, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.EmergencyContactPhone, "Phone", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.EmergencyContactPhone, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-sm-6">
#Html.LabelFor(model => model.EmergencyContactEmail, "Email", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.EmergencyContactEmail, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
</div>
<div class="panel-heading tabbable" tabindex="0"><h1>Driving Licence Details</h1></div>
<div class="panel-body">
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.DrivingLicenceNo, "Licence No", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.DrivingLicenceNo, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-sm-6">
#Html.LabelFor(model => model.DrivingLicenceExpiryDate, "Expiry Date", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.DrivingLicenceExpiryDate, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(model => model.DrivingLicenceImage, "Licence Image", htmlAttributes: new { #class = "control-label" })
<input type="file" name="uploadFile" />
</div>
<div class="col-sm-6">
#Html.LabelFor(model => model.DateofBirth, "Date of Birth", htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.DateofBirth, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
</div>
<input type="submit" class="btn btn-primary form-control" value="Submit" />
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">Notes</div>
<div class="panel-body">
<textarea rows="10" cols="15" class="form-control" id="Notes"></textarea>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">Invoice</div>
<div class="panel-body">
<div class="form-group row">
<div class="col-sm-6">
<label for="Paid">Paid</label>
<input class="form-control" type="text" id="Paid" placeholder="Amount Paid">
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<label for="Balance">Balance</label>
<input class="form-control" type="text" id="Balance" placeholder="Balance">
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<label for="Total">Total</label>
<input class="form-control" type="text" id="Total" placeholder="Total Amount">
</div>
</div>
Print Invoice
</div>
</div>
</div>
</div>
}
You have fields not properties, you need to change your view model definition to have properties like:
public class RegisterViewModel
{
public string Title { get; set;}
public string FirstName { get; set;}
//............
//............
}
The default model binder in ASP.NET MVC will only bind to publicly accessible properties, however you are currently using fields, which will not be bound.
You'll just need to decorate them with the necessary getters / setters as seen below to make them into properties :
public class RegisterViewModel
{
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Others omitted for brevity
}
Related
I used scaffolding to generate a view for the model below, in Visual Studio 2013 (.NET 4.5). I added the Display annotations afterwards. Why doesn't the LastName field appears above the FirstName field?
public class Order
{
[Display(Order=15001)]
public string FirstName { get; set; }
[Display(Order=15000)]
public string LastName { get; set; }
}
Does the DisplayAttribute.Order documentation say it only works on columns?
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.displayattribute?view=net-5.0
I'm reading Professional ASP.NET MVC 5 by Jon Galloway et al., that talks about doing this.
EDIT: the view (Create.cshtml). The original has more fields but I've omitted them like in the model:
#model MvcMusicStore.Models.Order
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Order</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", 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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I am new to ASP.NET MVC 5 and having some issues with binding only the multi-select section of the body during POST when submitting the form. The form renders correctly, with checkboxes being correctly selected. The form is scaffolded using visual studio (except the multi-select)
public class EditViewModel
{
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "LastName")]
public string LastName { get; set; }
public IList<RolesViewModel> Roles { get; set; }
}
public class RolesViewModel
{
public string RoleId { get; set; }
public string RoleName { get; set; }
public bool Selected { get; set; }
}
[HttpGet]
public async Task<ActionResult> Edit(string Id)
{...
var model = Mapper.Map<ApplicationUser, EditViewModel>(user);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(EditViewModel model)
{
}
#model BloggingService.Web.Models.EditViewModel
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Edit</title>
</head>
<body>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Edit</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Roles, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#for (int i = 0; i < Model.Roles.Count; i++)
{
#Html.CheckBoxFor(x => #Model.Roles[i].Selected,"test1");
<div class="form-check">
<input type="hidden" asp-for="#Model.Roles[i].RoleId" />
<input type="hidden" asp-for="#Model.Roles[i].RoleName" />
<input type="checkbox" asp-for="#Model.Roles[i].Selected" class="form-check-input" checked="#Model.Roles[i].Selected" />
<label class="form-check-label" asp-for="#Model.Roles[i].Selected">
#Model.Roles[i].RoleName
</label>
</div>
}
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Would really appreciate any insight.
I have managed to find the correct and cleaner approach for accomplishing such tasks by utilizing the HTML helper methods inside my for loop and now the data are able to bind correctly during data-binding.
#Html.HiddenFor(x => #Model.Roles[i].RoleId);
#Html.HiddenFor(x => #Model.Roles[i].RoleName);
#Html.CheckBoxFor(x => #Model.Roles[i].Selected);
I have create four models, then i have created a viewmodel that contains first four, i have created a view with controller that show this viewmodel;
When i created Actioresult Create (http post), i on't know how pass entire model.
viewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Avvisi.Models
{
public class PianoCompletoViewModels
{
public Guid Id { get; set; }
public DatiPiano DatiPiano { get; set; }
public DescrizionePiano descrizionePiano { get; set; }
public ImpresaBeneficiaria impresaBeneficiaria { get; set; }
public ResponsabilePiano responsabilePiano { get; set; }
public ProspettoFinanziario prospettoFinanziario { get;set; }
}
}
controller:
public ActionResult Create()
{
string UserID = Convert.ToString(User.Identity.GetUserId());
int AvvisoID = Convert.ToInt32(Session["AvvisoID"]);
ViewBag.FKCompartoID = new SelectList(db.Comparto, "CompartoID",
"Nome");
ViewBag.PianoID = new SelectList(db.DescrizionePiano,
"DescrizioneID", "PresentImpBenef_RelContAziend");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(PianoCompletoViewController PianoView)
{
if (ModelState.IsValid)
{
return View();
}
return View();
}
I expect that when i click on submit there is a model filled wiht property(other mmodels) For Example:
PianoView.model1.xxx
PianoView.model2.xxx
PianoView.model3.xxx
PianoView.model4.xxx
cshtml view:
#model Avvisi.Models.PianoCompletoViewModels
#{
ViewBag.Title = "Create";
}
<h2>Dati Piano</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Dati Piano</h4>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row" style="margin-left:0px;margin-right:0px">
<div class="form-group">
#Html.LabelFor(model => model.DatiPiano.NomePiano, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DatiPiano.NomePiano, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DatiPiano.NomePiano, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.descrizionePiano.PresentImpBenef_RelContAziend, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.descrizionePiano.PresentImpBenef_RelContAziend, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.descrizionePiano.PresentImpBenef_RelContAziend, "", new { #class = "text-danger" })
</div>
</div>
<div class="row">
<div class="form-group">
#Html.LabelFor(model => model.impresaBeneficiaria.CompanyName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.impresaBeneficiaria.CompanyName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.impresaBeneficiaria.CompanyName, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.responsabilePiano.Nome, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.responsabilePiano.Nome, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.responsabilePiano.Nome, "", 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" style="width:95%;background: #dedede;" />
</div>
</div>
</div>
}
I don't understand why it no let me to choose right properties(Models).
Can you help me, please???
You have to use html control name like this:
<input name="descrizionePiano.someProperty">
Then surely you have got value for it.
I've seen multiple instances of this question. Be that as it may, I still cannot figure out what the issue is with this post method not passing back the model to the controller. I've looked at naming conventions between the model being passed into the controller, as well as whether or not the read only fields were being passed in if I had removed them. Other than that, it might be the BindAttribute, binding the RoleIds of the multi-select to the model.
Here's my code:
the model:
public class UserDetail
{
public Guid Id { get; set; }
public List<string> RoleIds { get; set; }
public string DomainName { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
public string PhysicalDeliveryOfficeName { get; set; }
public string TenantDisplayId { get; set; }
public Boolean InitPassword { get; set; }
public Boolean Active { get; set; }
public Boolean SystemAdmin { get; set; }
public ICollection<RoleDetail> Roles { get; set; }
public IEnumerable<SelectedRoles> SelectedRoles { get; set; }
public MultiSelectList RoleOptions { get; set; }
public UserDetail()
{
Id = Id;
RoleIds = RoleIds;
FirstName = FirstName;
LastName = LastName;
Name = Name;
Active = Active;
EmailAddress = EmailAddress;
SystemAdmin = SystemAdmin;
}
}
cshtml:
#model IzendaEmbedded.Models.UserDetail
#using (Html.BeginForm("EditActiveDirectoryUser","ActiveDirectory",
FormMethod.Post, new {userDetail = Model}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<nav aria-label="breadcrumb">
<ol class="breadcrumb" style="height: 100px; padding-top: 20px; padding-left: 140px; background-color: #FFFFFF">
<li class="breadcrumb-item" style="font-family: arial; font-size:40px"><a href=#Url.Action("Index", "Home")>Izenda</a></li>
<li class="breadcrumb-item active" aria-current="page" style="font-family: arial; font-size:40px"><a href=#Url.Action("Parse", "ActiveDirectory")>Active Directory</a></li>
<li class="breadcrumb-item active" aria-current="page" style="font-family: arial; font-size:40px">Edit Izenda User</li>
</ol>
</nav>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UserName, "Account Name", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.EditorFor(model => model.UserName, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName, "First Name", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, "Last Name", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EmailAddress, "Email Address", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.EmailAddress, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Roles, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.ListBoxFor(model => model.RoleIds, Model.RoleOptions, new {#class = "form-control"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Active, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
<div class="checkbox">
#Html.EditorFor(model => model.Active)
#Html.ValidationMessageFor(model => model.Active, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-4">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
The controller post method:
[HttpPost]
public async Task<ActionResult> EditActiveDirectoryUser([Bind(Include =
"Id, Name, RoleIds")] UserDetail userDetail)
{
//save logic
}
This question already has an answer here:
Submit same Partial View called multiple times data to controller?
(1 answer)
Closed 5 years ago.
So I'm trying to create a Invoice form. In this form I want to fill in some customer details and add products, all in the same form.
I created a static example of how I want it to look:
The idea is to manually fill in a product, and if I want another product, I'd press the green plus glyphicon and add another product.
By clicking on the create button I want to submit this entire form with the customer details and the array/list of added products.
This is the code I have so far:
This is the view model that I use inside the view:
public class InvoiceViewModel
{
public Enums.Gender Gender { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string StreetName { get; set; }
public string HouseNumber { get; set; }
public string PostCode { get; set; }
public string City { get; set; }
public string PhoneNumber { get; set; }
public string EmailAddress { get; set; }
public List<InvoiceItemViewModel> InvoiceItems { get; set; }
}
This is the InvoiceItemViewModel that I use inside the partial view:
public class InvoiceItemViewModel
{
public string Name { get; set; }
public Enums.UnitType UnitType { get; set; }
public int Ammount { get; set; }
public decimal PriceWithoutVAT { get; set; }
}
This is the Create view:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Gender, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EnumDropDownListFor(model => model.Gender)
#Html.ValidationMessageFor(model => model.Gender, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PostCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PostCode, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PostCode, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.HouseNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.HouseNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.HouseNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StreetName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StreetName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.StreetName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.City, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.City, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.City, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PhoneNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PhoneNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PhoneNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EmailAddress, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EmailAddress, "", new { #class = "text-danger" })
</div>
</div>
<hr />
<h4>Products</h4>
<div class="container">
<div class="row">
<div class="col-md-6">Name</div>
<div class="col-md-2">Unit(s)</div>
<div class="col-md-2">Ammount</div>
<div class="col-md-2">Price</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-11">
#Html.Partial("~/Views/Invoice/InvoiceItem.cshtml")
</div>
</div>
<div class="row">
<div class="col-md-11">
#Html.Partial("~/Views/Invoice/InvoiceItem.cshtml")
</div>
</div>
<div class="row">
<div class="col-md-11">
#Html.Partial("~/Views/Invoice/InvoiceItem.cshtml")
</div>
<div class="col-md-1">
<span class="glyphicon glyphicon-plus" style="color: green;"></span>
</div>
</div>
</div>
</div>
<br />
<br />
<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>
}
And this is the partial view for an invoice item:
<div class="col-md-6">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-md-2">
#Html.EnumDropDownListFor(model => model.UnitType)
</div>
<div class="col-md-2">
#Html.EditorFor(model => model.Ammount, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-md-2">
#Html.EditorFor(model => model.PriceWithoutVAT, new { htmlAttributes = new { #class = "form-control" } })
</div>
So my question is, how do I add multiple invoice items to my form that I can use in the controller when I submit? I'm afraid that it's going to be a lot of javascript DOM manipulations.
Have a hidden template of the row on your page, then on the click of plus button, you can read the innerhtml of the template and append to list container.
Sample code
var templatehtml = $('#template')[0].innerHTML;
var newhtml = templatehtml
.replace(new RegExp('{{counter}}', 'g'), counter.toString())
.replace('{{counter++}}', (Number(counter) + Number(1)).toString());
$('#container').append(newhtml);
This will get you started, however it's not the most optimal code and the recommended way is to use a template library like JSRender