Form values not being passed to controller - c#

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!

Related

Pass multiple model to controller in ActionResult Create

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.

ASP.NET MVC POST won't send back second ocurrence of variable

The class Unidade:
public class Unidade
{
public int UnidadeId { get; set; }
public string Apelido { get; set; }
public string Descricao { get; set; }
}
Is used twice in the class Insumo, as Unidade and UnidadeConsumo
public class Insumo
{
public int InsumoId { get; set; }
public string Apelido { get; set; }
public string Descricao { get; set; }
public int UnidadeId { get; set; }
public Unidade Unidade { get; set; }
public int UnidadeConsumoId { get; set; }
public Unidade UnidadeConsumo { get; set; }
}
To edit Insumo there are two actions EDIT in the controller:
public ActionResult Edit(int? id)
{
Insumo insumo = db.Insumos.Find(id);
if (insumo == null) return HttpNotFound();
ViewBag.UnddId = new SelectList(db.Unidades, "UnidadeId", "Apelido", insumo.UnidadeId);
ViewBag.UndConsId = new SelectList(db.Unidades, "UnidadeId", "Apelido", insumo.UnidadeConsumoId);
return View(insumo);
}
And the POST EDIT:
[HttpPost]
public ActionResult Edit([Bind(Include = "InsumoId,Apelido,Descricao,UnidadeId,UnidadeConsumoId")] Insumo insumo)
{
if (ModelState.IsValid)
{
db.Entry(insumo).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.UnddId = new SelectList(db.Unidades, "UnidadeId", "Apelido", insumo.UnidadeId);
ViewBag.UndConsId = new SelectList(db.Unidades, "UnidadeId", "Apelido", insumo.UnidadeConsumoId);
return View(insumo);
}
The view to display the fields to edition, comprised of two dropdown lists to select both units is:
#model Gestor.Models.Insumo
#{
ViewBag.Title = "Alterar";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Alterar</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Insumo</h4>
<hr />
#Html.Partial("CopyEdit")
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Gravar" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Retornar a lista", "Index")
</div>
And the partial view CopyEdit in the center:
#model Gestor.Models.Insumo
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.InsumoId)
<div class="form-group">
#Html.LabelFor(model => model.Apelido, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Apelido, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Apelido, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Descricao, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Descricao, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Descricao, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UnidadeId, "Unidade", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("UnddId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.UnidadeId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UnidadeConsumoId, "Unidade de Consumo", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("UndConsId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.UnidadeConsumoId, "", new { #class = "text-danger" })
</div>
</div>
The problem is thta whrn returned to the POST Edit action, all fields are ok, but UnidadeConsumoId is always 0, what doesn't even exists in the database?
Can someone tell me why is it not returning the expected value, i.e. the selected value in the dropdown list reflecting the id of if?
Because your current code is rendering a SELECT element with name attribute value UndConsId.
<select class="form-control" name="UndConsId">
<!-- options -->
</select>
For model binding to work, the input element name attribute value should match with the parameter/property name used in the http post action method. Your parameter name is UnidadeConsumoId, not UndConsId
To fix this issue, pass UnidadeConsumoId as the first parameter of the DropDownList method call so that it will render the SELECT element with name UnidadeConsumoId. You can pass the ViewBag.UndConsId as the second parameter to explicitly specify the collection to be used to build the SELECT element.
This should work
#Html.DropDownList("UnidadeConsumoId", ViewBag.UndConsId as SelectList,
new { #class = "form-control" })

How to do a model binding of an entity that contains a list of another entity?

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
}

Error "A referential integrity constraint violation occurred"

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?

FluentValidation RuleFor attribute of Foreign Key

When I run the program I get a System.NullReferenceException on x.Album.Title == "Disintegration" in:
RuleFor(x => x.Contents)
.NotNull()
.When(x => x.Album.Title == "Disintegration");
How can I program this so that Contents is not accepted as Null when Album.Title == "Disintegration?
Model
[Validator(typeof(ReviewValidation))]
public class Review
{
public int ReviewID { get; set; }
[Display(Name = "Album")]
public int AlbumID { get; set; }
public virtual Album Album { get; set; }
public string Contents { get; set; }
[DataType(DataType.EmailAddress)]
public string ReviewerEmail { get; set; }
}
Validation
public class ReviewValidation : AbstractValidator<Review>
{
public ReviewValidation()
{
RuleFor(x => x.Contents)
.NotNull()
.When(x => x.Album.Title == "Disintegration");
}
}
Controller
public class ReviewsController : Controller
{
private StoreContext db = new StoreContext();
public ActionResult Create()
{
ViewBag.AlbumID = new SelectList(db.Albums, "AlbumID", "Title");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Review review)
{
if (ModelState.IsValid)
{
db.Reviews.Add(review);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.AlbumID = new SelectList(db.Albums, "AlbumID", "Title", review.AlbumID);
return View(review);
}
}
View
#model MVCMusicStore.Models.Review
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Review</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.AlbumID, "AlbumID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("AlbumID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.AlbumID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Contents, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Contents, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Contents, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ReviewerEmail, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ReviewerEmail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ReviewerEmail, "", 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")
}
Your view needs to pass the Album.Title back to the POST action in order to validate it. At the moment (from the code you posted), the Album property is null since it was never assigned an actual album, then in the view code where you post to the action, you didn't include the title.
Anyway, the exception you are getting is because Album prop is null in your code, and you are trying to validate its title.
What you could do also is to change the validation code, to only validate when album is not null
When(x => x.Album != null, () =>
{
RuleFor(x => x.Contents).NotNull().When(x => x.Album.Title == "Disintegration");
});

Categories

Resources