Autogentrated Entity models always true even custom class implemented - asp.net-mvc

I am using autogenerated entity model classes and than i used partial class with metadata to put validations on auto genetrated classes like below.
public class tblDepartmentCustom
{
[Key]
public int DepartmentId { get; set; }
[Required(ErrorMessage = "Department name is required")]
public string DepartmentName { get; set; }
}
[MetadataType(typeof(tblDepartmentCustom))]
public partial class tblDepartmentMaster
{
}
The original class that was generated by entity framework is given below.
public partial class tblDepartmentMaster
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public tblDepartmentMaster()
{
this.tblDesignationMasters = new HashSet<tblDesignationMaster>();
}
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<tblDesignationMaster> tblDesignationMasters { get; set; }
}
So the problem here is that whenever i try to validated model state it comes out to be true.below is the code.
#model EmployeeManager.Models.tblDepartmentCustom
#{
ViewBag.Title = "InsertDepartment";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}<div class="col-md-4">
#using (Html.BeginForm("InsertDepartment", "Departments", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<span class="error-class">#ViewBag.FoundError</span>
<br />
<label>Department Name</label>
#Html.TextBoxFor(m => m.DepartmentName, new { #class = "form-control" })
<br />
<input type="submit" class="btn btn-info" value="Add Department" />
}
</div>
And the action below.
[HttpGet]
public ActionResult InsertDepartment()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
[ActionName("InsertDepartment")]
public ActionResult InsertDepartmentPost()
{
using (PMSEntities dc = new PMSEntities())
{
tblDepartmentMaster dm = new tblDepartmentMaster();
TryUpdateModel(dm);
if(ModelState.IsValid)
{
dc.tblDepartmentMasters.Add(dm);
dc.SaveChanges();
return View("_Success");
}
else
{
ViewBag.FoundError = "Department name is required.";
return View();
}
}
}

In order for partial classes to work, both partials must have the same namespace. You don't have to move the actual files around your file structure, just edit the namespace of tblDepartmentCustom to match that of tblDepartmentMaster.

Related

Asp.NET MVC Product> ProductPhoto

I have 2 Separate Tables Products and Product Photo
When I examine any details in the products table, I want the pictures of that product to come. In that case, I pull it into the Detail table in a field called _UrunFotoPartitialView as # html.partitial ("") but always
The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.Urun_C7B3883A1159F8EE0177C29B1CA535182B157B3C5BB798ABCC8C2A72FB5CFED9', but this dictionary requires a model item of type 'Tututuncu.Models.UrunFotoViewModel'.
gives an error. How many days I have been dealing but I couldn't do it.
Ürün Class
public partial class Urun
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Urun()
{
this.Firma = new HashSet<Firma>();
this.Musteri = new HashSet<Musteri>();
this.Satis = new HashSet<Satis>();
}
public int UrunID { get; set; }
public Nullable<int> UrunFotoID { get; set; }
public Nullable<int> MarkaID { get; set; }
public string UrunAdi { get; set; }
public Nullable<decimal> UrunFiyat { get; set; }
public Nullable<decimal> UrunAlisFiyat { get; set; }
public Nullable<int> UrunStok { get; set; }
public string UrunAciklama { get; set; }
public Nullable<System.DateTime> UretimYili { get; set; }
public Nullable<System.DateTime> EklenmeTarihi { get; set; }
public Nullable<System.DateTime> GuncellenmeTarihi { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Firma> Firma { get; set; }
public virtual Markalar Markalar { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Musteri> Musteri { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Satis> Satis { get; set; }
public virtual UrunFoto UrunFoto { get; set; }
}
Ürün Foto Class
public partial class UrunFoto
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public UrunFoto()
{
this.Urun = new HashSet<Urun>();
}
public int FotoID { get; set; }
public Nullable<int> UrunFotoID { get; set; }
public string BuyukYol { get; set; }
public string OrtaYol { get; set; }
public string KucukYol { get; set; }
public Nullable<bool> Varsayilan { get; set; }
public string SiraNo { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Urun> Urun { get; set; }
}
My UrunController
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Tututuncu.Models;
namespace Tututuncu.Areas.Yonetim.Controllers
{
[Authorize]
public class UrunController : Controller
{
private StokDBEntities db = new StokDBEntities();
// GET: Yonetim/Urun
public ActionResult Index()
{
return RedirectToAction("Listele");
}
public ActionResult Listele()
{
var urun = db.Urun.Include(u => u.Markalar).Include(u => u.UrunFoto);
return View(urun.ToList());
}
public ActionResult Yeni()
{
ViewBag.MarkaID = new SelectList(db.Markalar, "MarkaID", "MarkaAd");
ViewBag.UrunFotoID = new SelectList(db.UrunFoto, "FotoID", "BuyukYol");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Yeni([Bind(Include = "UrunID,UrunFotoID,MarkaID,UrunAdi,UrunFiyat,UrunAlisFiyat,UrunStok,UrunAciklama,UretimYili,EklenmeTarihi,GuncellenmeTarihi")] Urun urun)
{
if (ModelState.IsValid)
{
db.Urun.Add(urun);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.MarkaID = new SelectList(db.Markalar, "MarkaID", "MarkaAd", urun.MarkaID);
ViewBag.UrunFotoID = new SelectList(db.UrunFoto, "FotoID", "BuyukYol", urun.UrunFotoID);
return View(urun);
}
public ActionResult Guncelle(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Urun urun = db.Urun.Find(id);
if (urun == null)
{
return HttpNotFound();
}
ViewBag.MarkaID = new SelectList(db.Markalar, "MarkaID", "MarkaAd", urun.MarkaID);
ViewBag.UrunFotoID = new SelectList(db.UrunFoto, "FotoID", "BuyukYol", urun.UrunFotoID);
return View(urun);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Guncelle([Bind(Include = "UrunID,UrunFotoID,MarkaID,UrunAdi,UrunFiyat,UrunAlisFiyat,UrunStok,UrunAciklama,UretimYili,EklenmeTarihi,GuncellenmeTarihi")] Urun urun)
{
if (ModelState.IsValid)
{
db.Entry(urun).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.MarkaID = new SelectList(db.Markalar, "MarkaID", "MarkaAd", urun.MarkaID);
ViewBag.UrunFotoID = new SelectList(db.UrunFoto, "FotoID", "BuyukYol", urun.UrunFotoID);
return View(urun);
}
public ActionResult Sil(int id)
{
var silinecekUrun = db.Urun.Find(id);
if (silinecekUrun == null)
return HttpNotFound();
db.Urun.Remove(silinecekUrun);
db.SaveChanges();
return RedirectToAction("Index", "Urun");
}
public ActionResult UrunResimEkle(int id)
{
Urun urun = db.Urun.Find(id);
ViewBag.Foto = urun;
return View(urun);
}
public ActionResult FotoListele(int id)
{
Urun urun = db.Urun.Find(id);
ViewBag.Foto = urun;
return View(urun);
}
[HttpPost]
public ActionResult UrunResimEkle(int uId, HttpPostedFileBase fileUpload)
{
if (fileUpload != null)
{
Image img = Image.FromStream(fileUpload.InputStream);
Bitmap kucukResim = new Bitmap(img, ResimAyar.UrunKucukBoyut);
Bitmap ortaResim = new Bitmap(img, ResimAyar.UrunOrtaBoyut);
Bitmap buyukResim = new Bitmap(img, ResimAyar.UrunBuyukBoyut);
string buyukYol = "/images/UrunFoto/Buyuk/" + Guid.NewGuid() + VirtualPathUtility.GetExtension(fileUpload.FileName);
string ortaYol = "/images/UrunFoto/Orta/" + Guid.NewGuid() + VirtualPathUtility.GetExtension(fileUpload.FileName);
string kucukYol = "/images/UrunFoto/Kucuk/" + Guid.NewGuid() + VirtualPathUtility.GetExtension(fileUpload.FileName);
kucukResim.Save(Server.MapPath(kucukYol));
ortaResim.Save(Server.MapPath(ortaYol));
buyukResim.Save(Server.MapPath(buyukYol));
UrunFoto rsm = new UrunFoto();
rsm.BuyukYol = buyukYol;
rsm.OrtaYol = ortaYol;
rsm.KucukYol = kucukYol;
rsm.UrunFotoID = uId;
if (db.UrunFoto.FirstOrDefault(x => x.UrunFotoID == uId && x.Varsayilan == false) != null)
rsm.Varsayilan = true;
else
rsm.Varsayilan = false;
db.UrunFoto.Add(rsm);
db.SaveChanges();
return Redirect(ControllerContext.HttpContext.Request.UrlReferrer.ToString());
}
return View(uId);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Urun View Page
#model IEnumerable<Tututuncu.Models.Urun>
#{
ViewBag.Title = "Ürüne Resim Ekle";
Layout = "~/Areas/Yonetim/Views/Shared/_Layout.cshtml";
}
<!-- Page Content -->
<div id="page-wrapper">
<div class="container-fluid">
<div class="row bg-title">
<div class="col-lg-3 col-md-4 col-sm-4 col-xs-12">
<h4 class="page-title">File Upload</h4>
</div>
<div class="col-lg-9 col-sm-8 col-md-8 col-xs-12">
<ol class="breadcrumb">
<li>Yönetim Paneli</li>
<li class="active">File Upload</li>
</ol>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- .row -->
<div class="row">
<div class="col-sm-12 ol-md-6 col-xs-12">
<div class="white-box">
<h3 class="box-title">File Upload1</h3>
<label for="input-file-now">Your so fresh input file — Default version</label>
<form action="/Yonetim/Urun/UrunResimEkle" method="post" enctype="multipart/form-data">
<input type="hidden" name="uId" value="#Model" />
<input type="file" name="fileUpload" />
<input type="submit" name="name" value="Kaydet" class="btn btn-primary" />
</form>
</div>
</div>
</div>
#Html.Partial("FotoListele")
</div>
</div>
My Partitial View Page
#model IEnumerable<Tututuncu.Models.UrunFoto>
#{
ViewBag.Title = "FotoListele";
Layout = "~/Areas/Yonetim/Views/Shared/_Layout.cshtml";
}
<h2>FotoListele</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.BuyukYol)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.BuyukYol)
</td>
</tr>
}
</table>
You have two model types.
Parent: #model IEnumerable<Tututuncu.Models.Urun>
Partial: #model IEnumerable<Tututuncu.Models.UrunFoto>
You're calling Partial using #Html.Partial("FotoListele")
You can use #Html.Partial("FotoListele", THE-NEW-MODEL-OF-LIST-UrunFoto)
When using Partial without passing the new model, it uses the parent model. Thus, it gets exception when trying to perform the casting.
You can either create a new Model that fits the Partial needs, or accept the parent model.
Note: partial class doesn't relate at all to razor engine Html.Partial. more on that Here

How to select SelectListItem inside a Razor View

I have a Model which i want to edit (Location).This model has a field called ActivityId.I am sending an array of ActivityId-s via ViewData to the view and transform them to a SelectList.
I want the ActivityId field (long) of the Location to be set with the selected item from the dropdownlist (string) - i need a conversion done somehow from string to long before entering the Post Action of the controller.(EditConfirmed)
Models:
[Table("location")]
public partial class Location
{
public Location()
{
StoryLocation = new HashSet<StoryLocation>();
UserStoryLocation = new HashSet<UserStoryLocation>();
}
[Column("id", TypeName = "bigint(20)")]
public long Id { get; set; }
[Column("description")]
[StringLength(255)]
public string Description { get; set; }
[Column("name")]
[StringLength(255)]
public string Name { get; set; }
[Column("activity_id", TypeName = "bigint(20)")]
public long? ActivityId { get; set; }
[ForeignKey("ActivityId")]
[InverseProperty("Location")]
public Activity Activity { get; set; }
}
}
[Table("activity")]
public partial class Activity
{
public Activity()
{
Location = new HashSet<Location>();
}
[Column("activity_id", TypeName = "bigint(20)")]
public long ActivityId { get; set; }
[Column("description")]
[StringLength(255)]
public string Description { get; set; }
[Column("name")]
[StringLength(255)]
public string Name { get; set; }
[Column("type")]
[StringLength(255)]
public string Type { get; set; }
[InverseProperty("Activity")]
public ICollection<Location> Location { get; set; }
}
Controller:
[HttpGet]
public IActionResult Edit(long id = 0)
{
Location loc = this.context.Locations.Find(id);
if (loc == null)
{
return NotFound();
}
ViewData[Constants.ViewData.TActivities]=this.context.Activities
.Select(elem=>
new SelectListItem
{
Text=elem.Name,
Value=elem.ActivityId.ToString()
}
).ToList();
return View(loc);
}
View
#using AdminMVC.Models
#using AdminMVC.ConfigConstants
#using Newtonsoft.Json
#model AdminMVC.Models.Location
#{
List<SelectListItem> dropActivities=ViewData[Constants.ViewData.TActivities] as List<SelectListItem>;
}
<html>
<head>
</head>
<body>
<div id="form">
</div>
<div id="page">
#using (Html.BeginForm("Edit","Location",FormMethod.Post))
{
<div id="table">
<label>Set Location:</label>
<table border="">
#Html.DisplayFor(x=>x.Id)
<tr>
<td>#Html.DisplayNameFor(x=>x.Name)</td>
<td>#Html.EditorFor(x=>x.Name)</td>
</tr>
<tr>
<td>#Html.DisplayNameFor(x=>x.Description)</td>
<td>#Html.EditorFor(x=>x.Description)</td>
</tr>
<div>
<label >Select Activity:</label>
#Html.DropDownList("Activity",dropActivities) //i need to somehow convert the selected value from the dropdown to long before the form is sent to the controller
</div>
</table>
</div>
<div id="control-panel">
<input type="submit" value="Edit">
</div>
}
</body>
</div>
</html>
Post to Controller
[HttpPost, ActionName("Edit")]
public IActionResult EditConfirmed(Location editLoc)
{
if (ModelState.IsValid)
{
this.context.Entry(editLoc).State = EntityState.Modified;
this.context.SaveChanges();
return RedirectToAction("Index");
}
return View(editLoc);
}
P.S:So far the ActivityId of the Location sent to the Post Action is null.I need it to be long.
I solved this problem using the ViewData component.I would first serialize the SelectList using NewtonSoft then i would add it to the ViewData dictionary.When rendering the view i would use the DropDownList razor Html Helper method.
Model
public class FixedLocation
{
[Column("id", TypeName = "bigint(20)")]
public long Id { get; set; }
[Column("coords")]
[StringLength(255)]
public string Coords { get; set; }
[Column("name")]
[StringLength(255)]
[Required]
public string Name { get; set; }
[Column("google_id")]
[StringLength(255)]
[Required]
public string GoogleId { get; set; }
}
Extension method for getting a List of SelectListItem
public static IEnumerable<SelectListItem> ToSelectList<T,Tkey,Tvalue>(
this IQueryable<T> myenum,
Func<T,(Tkey,Tvalue)>kvpair)
{
return myenum.Select(elem=>kvpair(elem))
.Select(tuple=>new SelectListItem{
Text=tuple.Item1.ToString(),
Value=tuple.Item2.ToString()
});
}
Controller:
public IActionResult Create()
{
Location targetLocation = new Location();
ViewData[Constants.ViewData.TFixedLocations]=
this.context.FixedLocation
.ToSelectList<FixedLocation,string,long>
(elem=>(elem.Name,elem.Id)).ToList();
return View(targetLocation);
}
View:
#using AdminMVC.Models
#model AdminMVC.Models.Location
#using AdminMVC.ConfigConstants
#{
dropFixedLocations=ViewData[Constants.ViewData.TFixedLocations] as List<SelectListItem>;
}
<div>
<label >Select FixedLocation:</label>
#Html.DropDownListFor(x=>Model.Id,dropFixedLocations)
</div>

ASP.NET MVC 5 Html.CheckboxFor only return default value on post

I have read the tutorials and prepared a list of checkboxes for the page. When the form is submitted, the Selected property only get the value false.
Is there something I missed?
The Model
public class SelectStudentModel
{
public int StudentID { get; set; }
public string CardID { get; set; }
public string Name { get; set; }
public bool Selected { get; set;}
}
The ViewModel
public class SelectStudentViewModel
{
public List<SelectStudentModel> VMList;
public SelectStudentViewModel()
{
VMList = SelectStudentModel.GETStudent();
}
}
The View
#using Student.Models
#model SelectStudentViewModel
#using (Html.BeginForm("AddStudent", "SectionStudent", FormMethod.Post, new { #role = "form" }))
{
#{ for (int i = 0; i < Model.VMList.Count(); i++)
{
<tr>
<td>#Html.CheckBoxFor(m => m.VMList[i].Selected)</td>
<td>#Html.DisplayFor(model => model.VMList[i].Name)</td>
</tr>
}
}
<input type="submit" value="submit" />
}#* end form *#
The Controller for posted data
[HttpPost]
public ActionResult AddStudent(SelectStudentViewModel model)
{
foreach (SelectStudentModel m in model.VMList)
{
Console.Write(m.Selected.ToString());
}
return PartialView("StudentSelectForm", model);
}
VMList is a field in your SelectStudentViewModel model. You need to change it to a property (with a getter/setter) so the DefaultModelBinder can set the values
public class SelectStudentViewModel
{
public List<SelectStudentModel> VMList { get; set; } // change
public SelectStudentViewModel()
{
VMList = SelectStudentModel.GETStudent();
}
}
Side note: Suggest you change #Html.DisplayFor(model => model.VMList[i].Name) to #Html.LabelFor(m => m.VMList[i].Selected, Model.MList[i].Name) so that you get a label associated with the checkbox

ViewModel property doesn't bind into controller action parameter

My problem is that my ViewModel property doesn't bind into an action parameter.
I think it'll be more clear if i just give you my code.
I have a model as follows:
namespace Sima3.Models
{
using System;
using System.Collections.Generic;
public partial class Usuario
{
public string Login { get; set; }
public string NombreCompleto { get; set; }
public short Organigrama { get; set; }
public int Interno { get; set; }
public string EMail { get; set; }
}
}
And i added DataAnnotations to this partial class in another file (Because this model was generated automatically by EntityFramework), note the remote validation on Login property:
namespace Sima3.Models
{
[MetadataType(typeof(UsuarioMetaData))]
public partial class Usuario
{
}
public class UsuarioMetaData
{
[Display(Name = "Nombre de Usuario")]
[Remote("NoExisteUsuario", "Validation")]
[Required]
public string Login { get; set; }
[Display(Name = "Nombre y Apellido")]
[Required]
public string NombreCompleto { get; set; }
[Display(Name = "Sector")]
[Required]
public short Organigrama { get; set; }
[Required]
public int Interno { get; set; }
[EmailAddress]
[Required]
public string EMail { get; set; }
}
}
Now, i have a ViewModel wich contains a property of type Usuario and some other stuff needed to render my View:
namespace Sima3.ViewModels.PedidoViewModels
{
public class AgregarViewModel
{
public Usuario Usuario { get; set; }
public Pedido Pedido { get; set; }
public SelectList ListaSectores { get; set; }
public SelectList ListaEstados { get; set; }
public SelectList ListaPrioridades { get; set; }
public SelectList ListaTipos { get; set; }
public SelectList ListaDirecciones { get; set; }
}
}
And my view looks as follows (I'll only post part of it, if u need to see more let me know):
#using (Ajax.BeginForm("Crear", "Usuario", null,
new AjaxOptions
{
OnSuccess = "UsuarioCreadoSuccess",
HttpMethod = "Post"
}
, new { #class = "form-horizontal", id = "FormUsuario" }))
{
#Html.AntiForgeryToken()
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title title">Nuevo Usuario</h4>
</div>
<div class="modal-body">
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Usuario.Login, new { #class = "col-lg-4 control-label" })
<div class="col-lg-7">
#Html.TextBoxFor(model => model.Usuario.Login, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.Usuario.Login)
</div>
</div>
Alright, the important part is the TextBoxFor, it renders me the next HTML:
<input class="form-control valid" data-val="true" data-val-remote="'Nombre de Usuario' is invalid." data-val-remote-additionalfields="*.Login" data-val-remote-url="/Validation/NoExisteUsuario" data-val-required="El campo Nombre de Usuario es obligatorio." id="Usuario_Login" name="Usuario.Login" type="text" value="">
As you see, the textbox name is: name="Usuario.Login"
And my controller action wich gets called by the Remote validation looks like this:
public JsonResult NoExisteUsuario([Bind(Prefix="Usuario")]string Login)
{
Usuario usuario = db.Usuarios.Find(Login);
if (usuario != null)
{
var MensajeDeError = string.Format("El usuario {0} ya existe", Login);
return Json(MensajeDeError, JsonRequestBehavior.AllowGet);
}
else
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
I set a breakpoint in this Action and it gets hit, but Login comes in null.
I checked with google chrome's debugger the http request header and it shows the form is getting submitted like this: Usuario.Login: asdasdasd.
The question is simple, how can i make it bind?
By the way, i'm using MVC5.
Thanks.
Well, i finally got it working, it seems i was setting the Prefix binding attribute wrongly.
Now my action looks like this:
public JsonResult NoExisteUsuario([Bind(Prefix="Usuario.Login")]string login)
{
Usuario usuario = db.Usuarios.Find(login);
if (usuario != null)
{
var MensajeDeError = string.Format("El usuario {0} ya existe", login);
return Json(MensajeDeError, JsonRequestBehavior.AllowGet);
}
else
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}

ASP.NET MVC DropDownFor Validation (Value cannot be null. Parameter name: source)

I am still struggling with learning ASP.NET MVC. All my form entries are required so I would like to do validation on them. For brevity I have paired my model down to Description (textbox) and Paradigm (dropdown). I am including Entry.cs, Paradigm.cs and EntryViewModel.cs Model classes and the Display.cshtml View.
[Bind(Exclude = "EntryId")]
public class Entry
{
[ScaffoldColumn(false)]
public int EntryId { get; set; }
[Required(ErrorMessage = "You must include a description.")]
public string Description { get; set; }
[Display(Name = "Type")]
[Required(ErrorMessage = "You must select a type.")]
public int ParadigmId { get; set; }
public virtual Paradigm Paradigm { get; set; }
}
public class Paradigm
{
[ScaffoldColumn(false)]
public int ParadigmId { get; set; }
[Required]
public string Name { get; set; }
public List<Entry> Entries { get; set; }
}
public class EntryViewModel
{
public Entry Entry { get; set; }
public IEnumerable<Entry> Entries { get; set; }
}
#model Pylon.Models.EntryViewModel
#{
ViewBag.Title = "Display";
}
<hr />
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Entry</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Entry.Description)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Entry.Description)
#Html.ValidationMessageFor(model => model.Entry.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Entry.ParadigmId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Entry.ParadigmId, ((IEnumerable<Pylon.Models.Paradigm>)ViewBag.PossibleParadigms).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.Name),
Value = option.ParadigmId.ToString(),
Selected = (Model != null) && (option.ParadigmId == Model.Entry.ParadigmId)
}))
<img src="../../Content/Images/add_icon.gif" />
#Html.ValidationMessageFor(model => model.Entry.ParadigmId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
If I submit the form without entering a description I would like validation to kick in and say "You must include a description." However instead I receive an ArgumentNullException on the DropDownFor line. http://www.wvha.org/temp/ArgumentNullException.png
What should I be doing? As an aside any decent books that cover ASP.NET MVC 3/Razor. I can follow along the basic tuts, but I go astray when I need to deviate to more advance features.
public class EntriesController : Controller
{
private readonly PylonContext _context = new PylonContext();
public ActionResult Display()
{
// DropDown
ViewBag.PossibleParadigms = _context.Paradigms;
var viewModel = new EntryViewModel {Entries = _context.Entries.ToList()};
return View(viewModel);
}
[HttpPost]
public ActionResult Display(EntryViewModel viewModel)
{
if (ModelState.IsValid)
{
_context.Entries.Add(viewModel.Entry);
_context.SaveChanges();
return RedirectToAction("Display");
}
return View(viewModel);
}
}
It's quite difficult to say without seeing your controller code, but looks like your ViewBag.PossibleParadigms might be null.
Does your insert/update controller action look something like this?
if (ModelState.IsValid) {
///...
} else {
return View(model);
}
If so, you need to put the PossibleParadigms back into the ViewBag (so to speak) before you return back to the view.
If you can post the relevant controller action code, it would be easier to know for sure.

Resources