EF database-first generated form won't validate - asp.net-mvc

I've just created a new controller, along with its CRUD forms, etc, with a database-first EF model/entity.
Its throwing a number of validation errors on save, but since the form has validators, I don't see why this would be so.
For reasons that are beyond me, I'm not getting any validation to happen at all. It just goes right in to the saveChanges() call, which promptly fails.
Here's the edit form:
#model StatementsApplication.DAL.StatementTask
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>StatementTask</legend>
<div class="editor-label">
#Html.LabelFor(model => model.sInitials)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sInitials)
#Html.ValidationMessageFor(model => model.sInitials)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.dtCompleted)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.dtCompleted)
#Html.ValidationMessageFor(model => model.dtCompleted)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.sGroupLabel)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sGroupLabel)
#Html.ValidationMessageFor(model => model.sGroupLabel)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.nGroupSequence)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.nGroupSequence)
#Html.ValidationMessageFor(model => model.nGroupSequence)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.sTaskType)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sTaskType)
#Html.ValidationMessageFor(model => model.sTaskType)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.sTaskLabel)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sTaskLabel)
#Html.ValidationMessageFor(model => model.sTaskLabel)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.nTaskSequence)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.nTaskSequence)
#Html.ValidationMessageFor(model => model.nTaskSequence)
</div>
#Html.HiddenFor(model => model.ID)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
and here's the generated model:
namespace StatementsApplication.DAL
{
using System;
using System.Collections.Generic;
public partial class StatementTask
{
public int StmtBatchID { get; set; }
public string sInitials { get; set; }
public Nullable<System.DateTime> dtCompleted { get; set; }
public string sGroupLabel { get; set; }
public double nGroupSequence { get; set; }
public string sTaskType { get; set; }
public string sTaskLabel { get; set; }
public double nTaskSequence { get; set; }
public int ID { get; set; }
public virtual StatementBatch tblStmtBatch { get; set; }
}
}
and here's the controller bits...
//
// GET: /StatementTask/Edit/5
public ActionResult Edit(int id = 0)
{
StatementTask statementtask = db.StatementTasks.Find(id);
if (statementtask == null)
{
return HttpNotFound();
}
ViewBag.StmtBatchID = new SelectList(db.StatementBatches, "ID", "sStatus", statementtask.StmtBatchID);
return View(statementtask);
}
//
// POST: /StatementTask/Edit/5
[HttpPost]
public ActionResult Edit(StatementTask statementtask)
{
if (ModelState.IsValid)
{
try
{
db.Entry(statementtask).State = EntityState.Modified;
db.SaveChanges();
}
catch (Exception ex) {
throw ex;
}
return RedirectToAction("Index");
}
ViewBag.StmtBatchID = new SelectList(db.StatementBatches, "ID", "sStatus", statementtask.StmtBatchID);
return View(statementtask);
}
Its a matter of some confusion for me as to why sInitials is throwing 'required' validation errors, as well as why sGroupLabel is throwing length validation errors.
Thanks

a) your model has no data validation annotations. As such, MVC doesn't do any validation, because you're not telling it what to validate.
b) You don't mention what you are submitting. Are you just submitting an empty form?

it appears that Data Annotations will resolve this issue
[Required(AllowEmptyStrings = true)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public object Note { get; set; }
via http://fendy-huang.blogspot.com/2011/04/how-to-pass-empty-string-in-entity.html

Related

DropDownListFor in MVC 4

I am having a hard time to show dropdownlist for in the view, the values will be populated from database. I am using MS SQL Server as the database.
I want to show a drop down list in ApplyingFor which will be populated from database.
Please help me out.
This is the Model
public class CandidateProfile
{
[Display(Name = "Candidate Name")]
[Required(ErrorMessage = "Provide a Name", AllowEmptyStrings=false)]
[DataType(DataType.Text)]
public string CandidateName { get; set; }
[Required(ErrorMessage = "Provide Your Address",AllowEmptyStrings = false)]
[Display(Name = "Address")]
[DataType(DataType.MultilineText)]
public string Address { get; set; }
[Display(Name = "Phone Number")]
[Required(ErrorMessage = "Provide a Phone Number")]
[RegularExpression("^([07][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | 8[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | 9[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])$", ErrorMessage = "Enter Valid Mobile Number")]
public string PhoneNumber { get; set; }
[Display (Name = "Email-Id")]
[Required(ErrorMessage="Provide an email-id")]
[EmailValidator]
public string EmailId { get; set; }
[Display (Name = "Applying For")]
public string **ApplyingFor** { get; set; }
[Display (Name = "Experience")]
[Required(ErrorMessage = "")]
public int Experience { get; set; }
[Display (Name = "Present Location")]
[Required(ErrorMessage = "")]
public string PresentLocation { get; set; }
}
public class ApplyingPositions
{
public IEnumerable<ApplyingPositions> ApplyingPosition { get; set; }
}
public class ApplyingPosition
{
public int APId { get; set; }
public string Designation { get; set; }
}
This is the View:
#model Recruitment.Models.CandidateProfile
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>CandidateProfile</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CandidateName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CandidateName)
#Html.ValidationMessageFor(model => model.CandidateName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Address)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address)
#Html.ValidationMessageFor(model => model.Address)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PhoneNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNumber)
#Html.ValidationMessageFor(model => model.PhoneNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmailId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmailId)
#Html.ValidationMessageFor(model => model.EmailId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplyingFor)
<div class="editor-field">
#Html.EditorFor(model => model.ApplyingFor)
#Html.ValidationMessageFor(model => model.ApplyingFor)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Experience)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Experience)
#Html.ValidationMessageFor(model => model.Experience)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PresentLocation)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PresentLocation)
#Html.ValidationMessageFor(model => model.PresentLocation)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
You need to pass the List of Options from your controller to view. So, before returning View
var listOfPositions = new List<ApplyingPosition>();
listOfPositions = //Call the service to populate the listOfPositions from Database here
ViewBag.PositionsList = new SelectList(listOfPositions, "APId", "Designation");
In your view instead of #Html.EditorFor(model => model.ApplyingFor)
#Html.DropDownListFor(m => m.ApplyingFor, (SelectList)ViewBag.PositionsList, "Select")
populate lstApplyingFor (list) form your DB. and in your controller
ViewBag.ApplyingFor = new SelectList(lstApplyingFor, "Id", "Name");
and in view:-
#Html.DropDownList(m => m.ApplyingFor,"ApplyingFor", "--Select--")
First-
1) You need to create the source for dropdown as-
var listForApplyingFor= db.Table.Select(o=> new SelectListItem{
Value=o.ID,
Text= o.Text
}).ToList();
ViewBag.ItemsApplyingFor= listForApplyingFor
.Cshtml View-
#Html.DropdownListFor(m=>m.ApplyingFor, new SelectList(ViewBag.ItemsApplyingFor,"Value","Text"),"Select...", htmlAttributes:new{ })
Let me know if it helps.

ASP.NET MVC bool value returned from the view is 1 or 0

I am using ASP.NET MVC, and I have some problems using a CheckBoxFor. Here is my problem:
I have the following code in the view:
#Html.CheckBoxFor(model => model.stade, new { #id = "stade" })
model.stade is of type bool. In my controller, I have:
//Editar
[HttpPost]
public ActionResult InvoiceType(int Id, string Name, string Code, string Stade)
{
clsInvoiceTypea Model = new clsInvoiceType();
Model.Id = Id;
Model.Name = Name;
Model.Code = Code;
Model.Stade = stade== "1" ? true : false;
return PartialView(Model);
}
I get an error, because when Model.Stade is submitted to the view the value is 1 or 0, and I get an error saying "Can not recognize the string as a valid Boolean", but if Model.stade is boolean why the model is submitted to the view like 0 or 1? How I can I resolve this?
Here goes my solution -
Let your Model be -
public class clsInvoiceTypea
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public bool stade { get; set; }
}
Let your HttpGet Action be -
public ActionResult GetInvoice()
{
clsInvoiceTypea type = new clsInvoiceTypea();
return View(type);
}
And the corresponding view -
#model YourValidNameSpace.clsInvoiceTypea
#{
ViewBag.Title = "GetInvoice";
}
<h2>GetInvoice</h2>
#using (Html.BeginForm("SubmitData","Home",FormMethod.Post)) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>clsInvoiceTypea</legend>
<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.Code)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Code)
#Html.ValidationMessageFor(model => model.Code)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.stade)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.stade)
#Html.ValidationMessageFor(model => model.stade)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Let the following be your HttpPost Action -
[HttpPost]
public ActionResult SubmitData(clsInvoiceTypea model)
{
return View();
}
When you run the code, you will get following view -
When you select the checkbox and hit the create button, if you put a breakpoint on POST method and check the value, you will get true.

ASP.NET MVC 4 Create method has null object

I have problem with creating object but I don't know why. I have null object in parameter in Post Create method and in ModelState I get this error:
{System.InvalidOperationException: The parameter conversion from type
'System.String' to type 'BlanskoMenu.Models.ActionOffer' failed
because no type converter can convert between these types. at
System.Web.Mvc.ValueProviderResult.ConvertSimpleType(CultureInfo
culture, Object value, Type destinationType) at
System.Web.Mvc.ValueProviderResult.UnwrapPossibleArrayType(CultureInfo
culture, Object value, Type destinationType) at
System.Web.Mvc.ValueProviderResult.ConvertTo(Type type, CultureInfo
culture) at
System.Web.Mvc.DefaultModelBinder.ConvertProviderResult(ModelStateDictionary
modelState, String modelStateKey, ValueProviderResult
valueProviderResult, Type destinationType)}
These are my methods in controller:
//
// GET: /Action/
public ActionResult Index()
{
var offers = _repository.GetAllActionOffers();
return View(offers);
}
//
// GET: /Action/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Action/Create
[HttpPost]
public ActionResult Create(ActionOffer action)
{
try
{
if (ModelState.IsValid)
{
_repository.CreateActionOffer(action);
return RedirectToAction("Index");
}
return View(action);
}
catch
{
return View(action);
}
}
This is my ActionOffer model:
public class ActionOffer
{
[Key]
public int Id { get; set; }
public string Text { get; set; }
public string Title { get; set; }
public string ImagePath { get; set; }
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }
[DataType(DataType.Date)]
public DateTime EndDate { get; set; }
}
And this is my Create view:
#model BlanskoMenu.Models.ActionOffer
#{
ViewBag.Title = "Vytvořit akční nabídku";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Vytvořit akční nabídku</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Akční nabídka</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Text)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Text)
#Html.ValidationMessageFor(model => model.Text)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ImagePath)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ImagePath)
#Html.ValidationMessageFor(model => model.ImagePath)
</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.EndDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EndDate)
#Html.ValidationMessageFor(model => model.EndDate)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Thanks for help
Try changing
public ActionResult Create(ActionOffer action)
to
public ActionResult Create(ActionOffer actionOffer)

Using one html.editorfor to fill in two model fields

Im trying to use only 1 html.editorfor to fill in two model field in each of my model.
I want the value of this editorfor to be also inserted to my Clientes0013.Client0013
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.Client00130012)
#Html.ValidationMessageFor(model => model.CanaClie0012.Client00130012)
</div>
and this one to be also inserted to Clientes0013.F1Pais00200013
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.F1Pais00200012)
#Html.ValidationMessageFor(model => model.CanaClie0012.F1Pais00200012)
</div>
Kindly show me what should be the right way of doing this.
My Table Model:
public partial class CanaClie0012
{
public string Client00130012 { get; set; }
public string F1Pais00200012 { get; set; }
public string F1Cana02530012 { get; set; }
public string Direcc0012 { get; set; }
public Nullable<System.DateTime> TmStmp0012 { get; set; }
}
public partial class Clientes0013
{
public string Client0013 { get; set; }
public string Nombre0013 { get; set; }
public string F1Pais00200013 { get; set; }
}
My Custom Model to combine the two table is:
public class ClientModel
{
public CanaClie0012 CanaClie0012 { get; set; }
public Clientes0013 Clientes0013 { get; set; }
}
My Controller:
[HttpPost]
public ActionResult ClientCreate(CanaClie0012 canaclie0012, Clientes0013 clientes0013)
{
ClientModel vm = new ClientModel();
if (ModelState.IsValid)
{
db.CanaClie0012.Add(canaclie0012);
db.Clientes0013.Add(clientes0013);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
My View:
#model MvcApplication1.Models.ClientModel
#{
ViewBag.Title = "ClientCreate";
}
<h2>ClientCreate</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>ClientModel</legend>
<div class="editor-label">
Client Name
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.Client00130012)
#Html.ValidationMessageFor(model => model.CanaClie0012.Client00130012)
</div>
<div class="editor-label">
Pais
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.F1Pais00200012)
#Html.ValidationMessageFor(model => model.CanaClie0012.F1Pais00200012)
</div>
<div class="editor-label">
Address
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CanaClie0012.Direcc0012)
#Html.ValidationMessageFor(model => model.CanaClie0012.Direcc0012)
</div>
<div class="editor-label">
Contact Number
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Clientes0013.Nombre0013)
#Html.ValidationMessageFor(model => model.Clientes0013.Nombre0013)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Got it.. modified my controller action to this one.
[HttpPost]
public ActionResult ClientCreate(CanaClie0012 canaclie0012, Clientes0013 clientes0013)
{
ClientModel vm = new ClientModel();
if (ModelState.IsValid)
{
clientes0013.Client0013 = canaclie0012.Client00130012;
clientes0013.F1Pais00200013 = canaclie0012.F1Pais00200012;
db.CanaClie0012.Add(canaclie0012);
db.Clientes0013.Add(clientes0013);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}

DateTime required in ModelState, however never set to be

I have a DateTime field in my form. For whatever reason, everytime I submit the form ModelState comes back as invalid and a message that my date time field (called PostDate) is required, even though in the view model I don't have the required attribute set.
Does anyone know why this would be happening as I'm going around in circles trying to figure it out.
Here is the view model
public class BlogViewModel
{
[Required]
public string Title { get; set; }
[Required]
public string Content { get; set; }
public bool Published { get; set; }
public DateTime PostDate { get; set; }
}
Here is the controller actions
public ActionResult Create()
{
return View();
}
//
// POST: /Admin/Blog/Create
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(BlogViewModel model)
{
if(ModelState.IsValid)
{
model.Content = HtmlSanitizer.SanitizeHtml(model.Content);
Services.BlogService.CreateBlogPost(model.Title, model.Content, User.Identity.Name);
return RedirectToAction("Index");
}
return View(model);
}
Here is the View
#using Payntbrush.Infrastructure.Mvc.Extensions
#model Payntbrush.Presentation.Demo.MVC3.Areas.Admin.Models.BlogViewModel
#Html.Resource(Html.ScriptTag("Areas/Admin/js/plugins/wysiwyg/jquery.wysiwyg.js"), ResourceType.Js)
<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((string)ViewBag.Action, "Blog", FormMethod.Post, new { Id = "BlogEditor" }))
{
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Content)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Content, new { #class = "wysiwyg blog-editor" })
#Html.ValidationMessageFor(model => model.Content)
</div>
<div class="editor-label">
Time of post (Only set this if you want to make a post appear to have been published at a different date.)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.PostDate, new{#class="datetimepicker"})
#Html.ValidationMessageFor(model => model.PostDate)
</div>
<div class="editor-label">
Published (Check to make this post live on the site)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.Published)
#Html.ValidationMessageFor(model => model.Published)
</div>
<p>
<input class="large awesome" type="submit" value="Create" />
#Html.ActionLink("Cancel", "Index", "Blog", null, new { #class = "large awesome cancel-button" })
</p>
}
<div>
</div>
If you leave the corresponding field empty your model will be invalid because DateTime is a value type. You should use a nullable DateTime if you want to allow empty values:
public DateTime? PostDate { get; set; }

Resources