How to make Optimistic Concurrency editing in Asp.net mvc 3 without using hiddenfields in the view? - asp.net-mvc-3

I'm studying asp.net mvc 3 right now and I'm following this tutorial Contoso University
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application
I'm in this part where editing a model is handled with Optimistic Concurrency
I'm aware that by using something like
[HttpPost]
public ActionResult Edit(Department department)
the model will automatically be binded, even without a hidden field for the id of the department to be edited, and the edit will not fail.
But whenever I try to remove the two hiddenfields in the view of this one:
#model MvcContosoUniversity.Models.Department
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Department</legend>
#Html.HiddenFor(model => model.DepartmentID)
#Html.HiddenFor(model => model.Timestamp)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Budget)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Budget)
#Html.ValidationMessageFor(model => model.Budget)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.StartDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.StartDate)
#Html.ValidationMessageFor(model => model.StartDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.InstructorID, "Administrator")
</div>
<div class="editor-field">
#Html.DropDownList("InstructorID", String.Empty)
#Html.ValidationMessageFor(model => model.InstructorID)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
I get an error in the controller, here's the code for the controller:
// GET: /Department/Edit/5
public ActionResult Edit(int id)
{
Department department = db.Departments.Find(id);
ViewBag.InstructorID = new SelectList(db.Instructors, "InstructorID", "FullName", department.InstructorID);
return View(department);
}
//
// POST: /Department/Edit/5
[HttpPost]
public ActionResult Edit(Department department)
{
try
{
if (ModelState.IsValid)
{
db.Entry(department).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
//Another option is to put the try-catch inside a function
try
{
var databaseValues = (Department)entry.GetDatabaseValues().ToObject();
var clientValues = (Department)entry.Entity;
if (databaseValues.Name != clientValues.Name)
ModelState.AddModelError("Name", "Current value: "
+ databaseValues.Name);
if (databaseValues.Budget != clientValues.Budget)
ModelState.AddModelError("Budget", "Current value: "
+ String.Format("{0:c}", databaseValues.Budget));
if (databaseValues.StartDate != clientValues.StartDate)
ModelState.AddModelError("StartDate", "Current value: "
+ String.Format("{0:d}", databaseValues.StartDate));
if (databaseValues.InstructorID != clientValues.InstructorID)
ModelState.AddModelError("InstructorID", "Current value: "
+ db.Instructors.Find(databaseValues.InstructorID).FullName);
ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
department.Timestamp = databaseValues.Timestamp;
}
catch(NullReferenceException e)
{
ModelState.AddModelError("","Error \n "+e.Message);
}
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
}
ViewBag.InstructorID = new SelectList(db.Instructors, "InstructorID", "FullName", department.InstructorID);
return View(department);
}
Here is the code for the model:
public class Department
{
public int DepartmentID { get; set; }
[Required(ErrorMessage = "Department name is required.")]
[MaxLength(50)]
public string Name { get; set; }
[DisplayFormat(DataFormatString = "{0:c}")]
[Required(ErrorMessage = "Budget is required.")]
[Column(TypeName = "money")]
public decimal? Budget { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[Required(ErrorMessage = "Start date is required.")]
public DateTime StartDate { get; set; }
[Display(Name = "Administrator")]
public int? InstructorID { get; set; }
public virtual Instructor Administrator { get; set; }
public virtual ICollection<Course> Courses { get; set; }
[Timestamp]
public Byte[] Timestamp { get; set; }
}
Is it possible to make it work without using hiddenfields?
Sir/Ma'am your answers would be of great help. Thank you++

You need to have the id value coming from somewhere, or that entity can't be saved... how does EF know what ID it's saving without it?
It doesn't have to be via hidden field; It's probably there in the query string from the initial GET request for the edit action.

Related

Checkboxlist - on Post: Create - NullReferenceException

StudentModel.
namespace mvcApp.Models
{
public class StudentModel
{
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Email Address")]
public string EmailAddress { get; set; }
public List<SchoolOrganization> Organizations { get; set; }
}
public class SchoolOrganization
{
public string Name { get; set; }
public bool IsInvolved { get; set; }
}
}
Student is involved in multiple organizations.
Controller
namespace mvcApp.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult StudentInformation()
{
// populate student with data
var student = new StudentModel() { FirstName = "Joe", LastName = "Doe", EmailAddress = "jdoe#hotmail.com"};
// Populate with Organizations
student.Organizations = new List<SchoolOrganization>();
student.Organizations.Add(new SchoolOrganization() { Name = "Math Club", IsInvolved = true});
student.Organizations.Add(new SchoolOrganization() { Name = "Chess Club", IsInvolved = false });
student.Organizations.Add(new SchoolOrganization() { Name = "Football", IsInvolved = true });
return View(student);
}
**[HttpPost]
public ActionResult StudentInformation(StudentModel student)
{
Response.Write("Name: " + student.FirstName);
foreach (var o in student.Organizations)
{
Response.Write(o.Name + " : " + o.IsInvolved.ToString());
}
return View();
}**
}
}
Data will be eventually populated from database.
View
#model mvcApp.Models.StudentModel
#{
ViewBag.Title = "StudentInformation";
}
<h2>StudentInformation</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>StudentModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmailAddress)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmailAddress)
#Html.ValidationMessageFor(model => model.EmailAddress)
</div>
<div>
<table>
<tr>
<td>Organization Name</td><td>Is Involved</td>
</tr>
#for (int i = 0; i < Model.Organizations.Count; i++) <== System.NullReferenceException here
{
#Html.HiddenFor(m => m.Organizations[i].IsInvolved)
<tr>
<td>#Html.DisplayFor(m => m.Organizations[i].Name)</td>
<td>#Html.CheckBoxFor(m => m.Organizations[i].IsInvolved)</td>
</tr>
}
</table>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
The above code displays fine with HttGet. However, when i try to update i get System.NullReferenceException. https://www.dropbox.com/s/dz0bg3hkd0yq8e3/studentInformation.png?dl=0
Can anyone please help figure it what's going on?
Thank you.
In the code sample you have provided; the HomeController's [HttpPost] ActionResult for StudentInformation does not create and pass a new instance of the updated object model to the view, but instead runs a basic debug.writeline routine. As a result the dependent view for the [HttpPost] view of "StudentInformation.cshtml", does not receive a populated instance of the updated model...
Setting a breakpoint on the first line of the model for the "StudentInformation.cshtml" page and running the application will demonstrate that the model referenced at the top of the page, has no data within it...
This is why the [HttpPost] version of the page simply renders the blank model, without any altered data values you may have created, UNTIL it gets to the section where the view is dependent on a count of new data values which must be present within the model that is called at first line of the page... to continue.
An empty data model set results in a null reference because there are no values to count within it.
In order to view an updated group of settings, The [HttpPost] version of the view model must be passed an instance of the model that returns the new information as in "return View(nameOfViewDataSet)" (you build a data set again, and pass it as a new version of the model, with revised form data present).
Until there is data passed via the return View statement relative to the [HttpPost] version of the StudentInformation ActionResult, to the actual view, there will be no display data, and the count function will continue to return a null value.
I hope that is helpful.

Asp.net mvc 3 model doesn't get automatically bind?

I'm studying asp.net mvc 3 right now and I'm following this tutorial Contoso University
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application
I'm in this part where editing a model is handled with Optimistic Concurrency
I'm aware that by using something like
[HttpPost]
public ActionResult Edit(Department department)
the model will automatically be binded, even without a hidden field for the id of the department to be edited, and the edit will not fail.
But whenever I try to remove the two hiddenfields in the view of this one:
#model MvcContosoUniversity.Models.Department
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Department</legend>
#Html.HiddenFor(model => model.DepartmentID)
#Html.HiddenFor(model => model.Timestamp)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Budget)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Budget)
#Html.ValidationMessageFor(model => model.Budget)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.StartDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.StartDate)
#Html.ValidationMessageFor(model => model.StartDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.InstructorID, "Administrator")
</div>
<div class="editor-field">
#Html.DropDownList("InstructorID", String.Empty)
#Html.ValidationMessageFor(model => model.InstructorID)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
I get an error in the controller, here's the code for the controller:
// GET: /Department/Edit/5
public ActionResult Edit(int id)
{
Department department = db.Departments.Find(id);
ViewBag.InstructorID = new SelectList(db.Instructors, "InstructorID", "FullName", department.InstructorID);
return View(department);
}
//
// POST: /Department/Edit/5
[HttpPost]
public ActionResult Edit(Department department)
{
try
{
if (ModelState.IsValid)
{
db.Entry(department).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
//Another option is to put the try-catch inside a function
try
{
var databaseValues = (Department)entry.GetDatabaseValues().ToObject();
var clientValues = (Department)entry.Entity;
if (databaseValues.Name != clientValues.Name)
ModelState.AddModelError("Name", "Current value: "
+ databaseValues.Name);
if (databaseValues.Budget != clientValues.Budget)
ModelState.AddModelError("Budget", "Current value: "
+ String.Format("{0:c}", databaseValues.Budget));
if (databaseValues.StartDate != clientValues.StartDate)
ModelState.AddModelError("StartDate", "Current value: "
+ String.Format("{0:d}", databaseValues.StartDate));
if (databaseValues.InstructorID != clientValues.InstructorID)
ModelState.AddModelError("InstructorID", "Current value: "
+ db.Instructors.Find(databaseValues.InstructorID).FullName);
ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
department.Timestamp = databaseValues.Timestamp;
}
catch(NullReferenceException e)
{
ModelState.AddModelError("","Error \n "+e.Message);
}
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
}
ViewBag.InstructorID = new SelectList(db.Instructors, "InstructorID", "FullName", department.InstructorID);
return View(department);
}
Here is the code for the model:
public class Department
{
public int DepartmentID { get; set; }
[Required(ErrorMessage = "Department name is required.")]
[MaxLength(50)]
public string Name { get; set; }
[DisplayFormat(DataFormatString = "{0:c}")]
[Required(ErrorMessage = "Budget is required.")]
[Column(TypeName = "money")]
public decimal? Budget { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[Required(ErrorMessage = "Start date is required.")]
public DateTime StartDate { get; set; }
[Display(Name = "Administrator")]
public int? InstructorID { get; set; }
public virtual Instructor Administrator { get; set; }
public virtual ICollection<Course> Courses { get; set; }
[Timestamp]
public Byte[] Timestamp { get; set; }
}
Is it possible to make it work without using hiddenfields?
Sir/Ma'am your answers would be of great help. Thank you++
Based on your HttpPost action signature, no, this isn't possible. You're performing an Edit so it will need the Id of the row that is being updated. Since you're not mapping the Id in the action method signature, and the hidden fields holding that information aren't there, the id will never get mapped to the Department model. The result being that you would try to perform an update without a row id.
EDIT: You could modify your action signature like so: Edit(int id, Department department), but then you'd have to manually set the department.Id to the id passed and that would seem to make the model somewhat disjointed.

Uploading and converting an image/file into a mssql databse

I would like to save an image/file into a sql-database in an asp.net mvc3 project. I found some examples where they have to save the image into a database with nothing else. When I want to add a "Inzending" instance in my database with the "Create" methode from my Controller, I also need to put the file into an byte array. I have to insert all the information into my database at the same time, because no field may be null. I hope someone can help me with this, I'm just starting with it in school and this is the first real big problem i have to solve ( i find it quite hard to solve). some of my code I already wrote:
Controller:
[HttpPost]
public ActionResult Create(INZENDING inzending)
{
string user = User.Identity.Name;
var users = db.aspnet_Users.Single(p => p.UserName == user).UserId;
inzending.Userid = users;
int id = db.INZENDINGs.Count() + 1;
inzending.InzendingNr = id;
if (ModelState.IsValid)
{
db.INZENDINGs.Add(inzending);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ErfgoedNr = new SelectList(db.ERFGOEDFICHEs, "ErfgoedNr", "Naam", inzending.ErfgoedNr);
ViewBag.Aard = new SelectList(db.INPUT_AARD, "Aard", "Aard", inzending.Aard);
ViewBag.Type = new SelectList(db.INPUTTYPEs, "type", "type", inzending.Type);
ViewBag.Status = new SelectList(db.STATUS, "Waarde", "Waarde", inzending.Status);
return View(inzending);
}
view :
#model Erfgoed.Models.INZENDING
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>INZENDING</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Titel)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Titel)
#Html.ValidationMessageFor(model => model.Titel)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Auteur)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Auteur)
#Html.ValidationMessageFor(model => model.Auteur)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Datum)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Datum)
#Html.ValidationMessageFor(model => model.Datum)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.bestandsgrootte)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.bestandsgrootte)
#Html.ValidationMessageFor(model => model.bestandsgrootte)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Type, "INPUTTYPE")
</div>
<div class="editor-field">
#Html.DropDownList("Type", String.Empty)
#Html.ValidationMessageFor(model => model.Type)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Aard, "INPUT_AARD")
</div>
<div class="editor-field">
#Html.DropDownList("Aard", String.Empty)
#Html.ValidationMessageFor(model => model.Aard)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ErfgoedNr, "ERFGOEDFICHE")
</div>
<div class="editor-field">
#Html.DropDownList("ErfgoedNr", String.Empty)
#Html.ValidationMessageFor(model => model.ErfgoedNr)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.bestand, "Bestand");
</div>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Model:
namespace Erfgoed.Models
{
using System;
using System.Collections.Generic;
public partial class INZENDING
{
public int InzendingNr { get; set; }
public string Titel { get; set; }
public string Auteur { get; set; }
public System.DateTime Datum { get; set; }
public string bestandsgrootte { get; set; }
public string Type { get; set; }
public string Aard { get; set; }
public byte[] bestand { get; set; }
public System.Guid Userid { get; set; }
public int ErfgoedNr { get; set; }
public string Status { get; set; }
public virtual aspnet_Membership aspnet_Membership { get; set; }
public virtual ERFGOEDFICHE ERFGOEDFICHE { get; set; }
public virtual INPUT_AARD INPUT_AARD { get; set; }
public virtual INPUTTYPE INPUTTYPE { get; set; }
public virtual STATUS STATUS1 { get; set; }
}
}
[HttpPost]
public ActionResult Create(HttpPostedFileBase file, FormCollection collection)
{
var attachment = new Attachment();
if(TryUpdateModel(attachment))
{
long length =
file.InputStream.Length;
attachment.Data = new byte[length];
file.InputStream.Read(attachment.Data, 0, (int)length);
attachmentRepository.Add(attachment);
attachmentRepository.Save();
return RedirectToAction("Index");
}
return null;
}
Here's how i'm saving file in ms sql database. Sorry if i wrongly understood your question

How to update a domain object with ViewModel and AutoMapper using Entity framework?

How do i update a domain object with ViewModel with AutoMapper using Entity framework?
I have a View to edit a Question entity.
This is my Edit action:
public ActionResult Edit(int id)
{
var question = db.Question.Single(q => q.question_id == id);
Mapper.CreateMap<Question, EditQuestionViewModel>();
EditQuestionViewModel eqvm = Mapper.Map<Question, EditQuestionViewModel>(question);
eqvm.QuestionTypes = new SelectList(db.Question_Type, "type_code", "type_description", question.type_code);
eqvm.Categories = new SelectList(db.Category, "category_id", "category_name", question.category_id);
eqvm.Visibility = new SelectList(new Dictionary<int, string> {
{ 1, "Ja"},
{ 0, "Nej"}
}, "Key", "Value");
return View(eqvm);
}
And my ViewModel looks like this:
public class EditQuestionViewModel
{
public int question_id { get; set; }
public string question_wording { get; set; }
public bool visible { get; set; }
public int question_number { get; set; }
public string help_text { get; set; }
public Category Category { get; set; }
public Question_Type Question_Type { get; set; }
public string SelectedCategory { get; set; }
public string SelectedQuestionType { get; set; }
public SelectList Categories { get; set; }
public SelectList QuestionTypes { get; set; }
public SelectList Visibility { get; set; }
public string RefUrl { get; set; }
}
This is the View:
#using (Html.BeginForm("Edit", "AdminQuestion", FormMethod.Post))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Spørgsmål</legend>
<div class="editor-label">
#Html.LabelFor(model => model.question_wording, "Spørgsmål")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.question_wording, new { #class = "required", rows = 3, cols = 50 })
#Html.ValidationMessageFor(model => model.question_wording)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SelectedCategory, "Hvilken kategori tilhører dette spørgsmål?")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SelectedCategory, Model.Categories)
#Html.ValidationMessageFor(model => model.SelectedCategory)
</div>
<div class="editor-label">
#Html.LabelFor(x => x.SelectedQuestionType, "Spørgsmålstype")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SelectedQuestionType, Model.QuestionTypes)
#Html.ValidationMessageFor(model => model.SelectedQuestionType)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.visible, "Skal dette spørgsmål være synligt?")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.visible, Model.Visibility)
#Html.ValidationMessageFor(model => model.visible)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.question_number, "Hvilket nummer har spørgsmålet inden for sin kategori?")
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.question_number, new { #class = "required digits" })
#Html.ValidationMessageFor(model => model.question_number)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.help_text, "Hjælpetekst som hjælper brugeren med at forstå spørgsmålet:")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.help_text, new { rows = 20, cols = 50 })
#Html.ValidationMessageFor(model => model.help_text)
</div>
<br />
<input type="submit" value="Gem" />
</fieldset>
How do i update the entity when i submit the form ?
How should the mapping between the ViewModel and EF Model look like, using AutoMapper?
The properties
public string SelectedCategory { get; set; }
public string SelectedQuestionType { get; set; }
In the ViewModel are supposed to be linked with category_id and type_code in the EF model
Also notice the property
public bool visible { get; set; }
I use BIT in my database. Will this work with the values 0 and 1, which is use in the SelectList?
Thanks!
you would need to get the object from entity framework, and then use automapper like this:
var item = repository.getbyid(model.Id);
_mappingEngine.Map(viewModel, item);
repository.save(item);
When you submit your form, you need to have an action on your controller that will handle the post to the server.
So in addition to the Edit action you currently have, you will need to have another action defined like so:
[HttpPost]
public ActionResult Edit(EditQuestionViewModel model)
{
//Do the mapping to from your ViewModel to the EF model here
return View();
}
What this does is sets up a handler so your form can post the data back to the controller and it will bind your fields on your form to the model parameter.
Once you have done this, you can simply map the model back to EF and persist it to the database.
Also, using a bool is perfectly valid and EF will translate and save it as a 0 or 1 in the database for you.

jQuery and ASP.NEt MVC validation: Prevent validation on server

I have model that looks like this:
public class Lesson
{
public int Id { get; set; }
[Required(ErrorMessage = "Naam voor de les is verplicht")]
[Display(Name="Naam")]
public string Name { get; set; }
[Required(ErrorMessage = "Tijd is verplicht")]
[Display(Name="Tijd")]
public string Time { get; set; }
//Prijs is default exclusief BTW
[Required(ErrorMessage = "Prijs is verplicht")]
[Display(Name="Prijs (excl btw)")]
public double Price { get; set; }
[Display(Name = "Maximum aantal leerlingen")]
public int MaxStudents { get; set; }
}
And a create view that looks like this:
<div>
<div>
#Html.LabelFor(model => model.Name)
</div>
<div>
#Html.TextBoxFor(model => model.Name, new { #class = "gt-form-text" })
#Html.ValidationMessageFor(model => model.Name)
</div>
<div>
#Html.LabelFor(model => model.Time)
</div>
<div>
#Html.TextBoxFor(model => model.Time, new { #class = "gt-form-text" })
#Html.ValidationMessageFor(model => model.Time)
</div>
<div>
#Html.LabelFor(model => model.Price)
</div>
<div>
#Html.TextBoxFor(model => model.Price, new { #class = "gt-form-text" })
#Html.ValidationMessageFor(model => model.Price)
</div>
<div>
#Html.LabelFor(model => model.MaxStudents)
</div>
<div>
#Html.TextBoxFor(model => model.MaxStudents,
new { #class = "gt-form-text" })
#Html.ValidationMessageFor(model => model.MaxStudents)
</div>
</div>
In the Application_Start() method I set DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes to false.
MaxStudents is nullable and not required, nevertheless, if MaxStudents is null, the Modelstate is not valid (ModelState.IsValid = false).
My errormessage is not shown, instead of that I get the errormessage is A value is required.
What can I do to get ModelState.IsValid to be true?
Someone shared this with me, and I'll pass it on in case it helps. Sometimes those validation errors get swallowed up and are hard to find. When I was having a similar issue, I added this code to my ActionResult (HttpPost) and it got me right to the error in question.
try
{
db.Entry(myModel).State = EntityState.Modified;
db.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
} // }

Resources