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.
Related
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Why is EditorFor in my ASP.NET MVC 2 application throwing ArgumentNullException?
(1 answer)
Closed 2 years ago.
I have a pretty simple program so far, meaning it shouldn't be too hard to find the problem.
When I load the website I get the following error on line 21 of the SignUp view:
#Html.EditorFor(model => model.EmployeeId, new { htmlAttributes = new { #class = "form-control" } })
System.NullReferenceException: 'Object reference not set to an instance of an object.'
The model class
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
namespace MVCApp.Models
{
public class EmployeeModel
{
public int EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string ConfirmEmail { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
}
The controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCApp.Controllers
{
public class HomeController : Controller
{
...
public ActionResult SignUp()
{
ViewBag.Message = "Employee Sign Up";
return View();
}
}
}
The view (autogenerated)
#model MVCApp.Models.EmployeeModel
#{
ViewBag.Title = "Employee Sign Up";
}
<h2>SignUp</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>EmployeeModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.EmployeeId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EmployeeId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EmployeeId, "", 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.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>
<div class="form-group">
#Html.LabelFor(model => model.ConfirmEmail, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ConfirmEmail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ConfirmEmail, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ConfirmPassword, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ConfirmPassword, "", 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'm using Microsoft Visual Studio Community 2019 Version 16.7.2 and .NET Framework 4.7.2
Thank you
I want make a form using a model that contains a list of another entity, but I don't know how to do it. Note: without Entity Framework.
I have use only a model that contains only its fields, but not another entity.
My code is:
Tarea.cs
public class Tarea
{
public int ID { get; set; }
public string NombreTarea { get; set; }
public int TiempoTarea { get; set; }
}
Employee.cs
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime JoiningDate { get; set; }
public int Age { get; set; }
public List<Tarea> Tareas { get; set; }
}
And my view is:
Create.cshtml
#model MVCSimpleApp.Models.Employee
....
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Employee</h4>
<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-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.JoiningDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.JoiningDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.JoiningDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Age, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Age, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Age, "", 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>
}
I don't know how to put the List<Tarea> in the form. Thanks in advance.
For Example, if we want to collect two sets of Tareas model,
View Code:
#for (var item = 0; item < 2; item++)
{
#Html.HiddenFor(model => model.Tareas[item].ID)
#Html.TextBoxFor(model => model.Tareas[item].NombreTarea, new { #class = "form-control" })
#Html.TextBoxFor(model => model.Tareas[item].TiempoTarea, new { #class = "form-control" })
}
And in the Post Create Action Method..
[HttpPost]
public ActionResult Create(Employee model)
{
// here we we get the all values given from the view ...
string example = model.Name;
List<Tarea> list = model.Tareas; // and iterate through model.Tareas to get List model values
}
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
My Controller Method:
[HttpGet]
public ActionResult NewInventory()
{
return View();
}
[HttpPost]
public async Task<ActionResult> NewInventory(string bookID, string ttlin, string lowin, string Outnow)
{
// test values passed, etc.....
}
So far only the "lowin" value is being passed correctly. All the other values are set to "0" (I believe due to the datatypes being set to "not null" in SQL DB). Why is this?
I assume because only one value is passed correctly and no exceptions are thrown, then the view page code is missing the other the fields to pass.
View Code :
#model LibraryMS.Inventory
#{
ViewBag.Title = "newinventory";
}
<h2>newinventory</h2>
#using (Html.BeginForm("NewInventory","BookInfo", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Inventory</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.BookID, "BookID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BookID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.BookID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TotalIn, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TotalIn, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TotalIn, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LowIn, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LowIn, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LowIn, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Out, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Out, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Out, "", 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>
By looking, the values are being passed.
Turns out that the controller method's parameters needs to be spelled the same as what is going to be passed to it. For example:
With the autogenerated form using html helper #Beginform, all the fields are present. But the parameters in the controller method are not the same as the inventory's class fields.
public partial class Inventory
{
public string BookID { get; set; }
public short TotalIn { get; set; }
public short LowIn { get; set; }
public short Out { get; set; }
public virtual BookInfo BookInfo { get; set; }
}
Compared to the paramters:
[HttpPost]
public async Task<ActionResult> NewInventory(string bookID, string ttlin, string lowin, string Outnow)
{
// test values passed, etc.....
}
The fix was to ofcoarse make the params the same, capitalization does not matter.
[HttpPost]
public async Task<ActionResult> NewInventory(string bookID, string totalin, string lowin, string Out)
{
// test values passed, etc.....
}
It was a simple mistake but took me some time to figure this out. Hopefully this helped someone else!
Can you please help me with my code?
I have 2 models:
public class Author
{
public int Id { get; set; }
public string AuthorName { get; set; }
public IEnumerable<Book> Books { get; set; }
}
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public int YearPublish { get; set; }
public int Price { get; set; }
public int? AuthorId { get; set; } //FK
public Author Author { get; set; } //navigation property
}
And trying to make an Edit function.
Controller code:
// GET: Books/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return HttpNotFound();
}
Book bookEdit = dbBooks.Books.Include(a => a.Author).Where(a => a.AuthorId == id).Single();
return View(bookEdit);
}
// POST: Books/Edit/5
[HttpPost]
public ActionResult Edit(Book book)
{
if (ModelState.IsValid)
{
// TODO: Add update logic here
//book.Author = null; //AuthorName cant be edited
dbBooks.Entry(book).State = EntityState.Modified;
dbBooks.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
And my View:
<div class="form-horizontal">
<h4>Book</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.Author.AuthorName, "AuthorName", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Author.AuthorName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Author.AuthorName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.YearPublish, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.YearPublish, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.YearPublish, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Price, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Price, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Price, "", new { #class = "text-danger" })
</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>
And when i try just to click Save button (even if i dont do any changes) an error occured:
A referential integrity constraint violation occurred: The property value(s) of 'Author.Id' on one end of a relationship do not match the property value(s) of 'Book.AuthorId' on the other end.
Error is in dbBooks.Entry(book).State = EntityState.Modified;
If I try to add book.Author = null; it is logically than my AuthorNames` start to disappear...
Also I was trying to put something in Html.HiddenFor, but maybe I was doing something wrong, but nothing changed.
Well, you couldn't modify AuthorName in Book's editor view. You need another view for Author to modify it.
book.Author - cannot be null, becouse its navigation property and can only be like readonly mode. So just remove editormodel for author.authorname
Modified books list:
Book bookEdit = dbBooks.Books.ToList().Where(a => a.Id == id).SingleOrDefault();
Look what you need to do, i got it now. You just need selectList of all Author's and in a view name will be auto selected on AuthorId book's field.
Make new one form-group with
<div class="form-group">
#Html.LabelFor(model => model.AuthorId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#(Html.DropDownListFor(p => p.AuthorId, (SelectList)ViewBag.Authors, new { #class = "form-control" }))
#Html.ValidationMessageFor(model => model.AuthorId, "", new { #class = "text-danger" })
</div>
</div>
And in Your Edit action:
// GET: Books/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return HttpNotFound();
}
Book bookEdit = dbBooks.Books.Where(a => a.Id == id).Single();
// UPDATED
var list = dbBooks.Books.Select(x => new { ID = x.Id, AuthorName = x.AuthorName });
ViewBag.Authors = new SelectList(list, "Id", "AuthorName");
// UPDATED
return View(bookEdit);
}
Again many thanks!
But using DropDownList dont allow me to edit Author`s name.. But that solution is rly good.
I need to edit all 4 fields like name, title, year and price.
I try to make something like composite model:
public class BookAuthorCompositeModel
{
public Author author { get; set; }
public Book book { get; set; }
}
Change my get method:
// GET: Books/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return HttpNotFound();
}
var compModel = new BookAuthorCompositeModel();
compModel.book = dbBooks.Books.ToList().Where(a => a.Id == id).SingleOrDefault();
compModel.author = dbBooks.Authors.ToList().Where(x => x.Id == id).SingleOrDefault();
return View(bookEdit);
}
and it displays all I need (i tap "edit" and see information about name, title, year and price).
My view is:
#model BookStorage.Models.BookAuthorCompositeModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Book</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.book.Id)
<div class="form-group">
#Html.LabelFor(model => model.author.AuthorName, "AuthorName", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.author.AuthorName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.author.AuthorName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.YearPublish, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.YearPublish, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.YearPublish, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.Price, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.Price, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.Price, "", new { #class = "text-danger" })
</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>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
but something wrong is in Post method:
[HttpPost]
public ActionResult Edit(Book book)
{
if (ModelState.IsValid)
{
dbBooks.Entry(BAmodel.book).State = EntityState.Modified;
dbBooks.Entry(BAmodel.author).State = EntityState.Modified;
dbBooks.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
dbBooks.SaveChanges(); leads to error..
I think using this kind of ViewModel helps to edit all rows, but it doesnt sade data to DB...
Maybe you could help with this please?