Validate function of IValidatableObject not working - asp.net

I have a "Review" Class:
public class Review : IValidatableObject
{
public int ReviewId { get; set; }
[DisplayName("Digning Date")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
public DateTime Created { get; set; }
[Range(1, 10)]
public int Rating { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string Body { get; set; }
public int RestaurantId { get; set; }
public virtual Restaurant Resturant { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var fields = new[]{ "Created"};
if(Created > DateTime.Now)
{
yield return new ValidationResult("Created date cannot be in the future.", fields);
}
if (Created < DateTime.Now.AddYears(-1))
{
yield return new ValidationResult("Created date cannot be to far in the past.", fields);
}
}
}
which uses Validate method of IValidatableObject to validate Create property. also this is my cshtml code:
#model OdeToFood.Models.Review
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#section scripts
{
<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>Review</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Created)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Created)
#Html.ValidationMessageFor(model => model.Created)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Rating)
#Html.ValidationMessageFor(model => model.Rating)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Body)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Body)
#Html.ValidationMessageFor(model => model.Body)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
The Validate method simply check wether the year of date of Create is in present year(2012) or last year(2011). So if user enter 2000 as year he should get error: "Created date cannot be in the future.". But i does not work!
also this is my configuration in web.config:
<appSettings>
<add key="webpages:Version" value="1.0.0.0" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
also this my controller code:
public ActionResult Create()
{
return View(new Review());
}
//
// POST: /Reviews/Create
[HttpPost]
public ActionResult Create(int restaurantId, Review newReview)
{
try
{
//_db is my DBContext
var restaurant = _db.Restaurants.Single(r => r.RestaurantId == restaurantId);
newReview.Created = DateTime.Now;
restaurant.Reviews.Add(newReview);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch(System.Data.Entity.Validation.DbEntityValidationException ex)
{
return View();
}
}
What i must to do?
Thanks

It's getting called twice because once when you post and the model binder binds to newReview, and once when you call SaveChanges.
What you should do is when you post check if ModelState.IsValid= false, if so return View(newReview);
in addition your DbEntityValidationException should return View(newReview);
and lastly check out the action filter I wrote here - you don't need to have a try catch - simply use the attribute on your controller's method or register it on application startup like is done with HandleError
MapEntityExceptionsToModelErrorsAttribute

Related

asp.Net MVC view model is empty on post

I have a complex view model that I am passing to a create view. When I enter data on the page and post it the model is empty. Both the fields in the sub-object and the "test" field are empty. Why?
public class ContactIncident
{
[Key]
public int Id { get; set; }
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[Display(Name = "Incident Date")]
[DataType(DataType.Date)]
public DateTime? IncidentDateTime { get; set; }
[Display(Name = "Follow Up Date")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
[DataType(DataType.Date)]
public DateTime? FollowUpDate { get; set; }
}
public class IncidentManager
{
public ContactIncident Incident { get; set; }
public string Test { get; set; }
}
public ActionResult Create(int? id)
{
IncidentManager im = new IncidentManager();
ContactIncident ci = new ContactIncident();
ci.IncidentDateTime = DateTime.Now;
ci.FollowUpDate = DateTime.Now.AddDays(14);
im.Incident = ci;
return View(im);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(IncidentManager im)
{
if (ModelState.IsValid)
{
ContactIncident ci = new ContactIncident();
ci.IncidentDateTime = incident.Incident.IncidentDateTime;
ci.Description = im.Incident.Description;
return RedirectToAction("Index");
}
return View(incident);
}
View:
#model MyApp.Web.ViewModels.IncidentManager
#{
ViewBag.Title = "Edit Incident";
}
<h4>#ViewBag.Title</h4>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal well">
#Html.ValidationSummary(true)
#Html.EditorFor(model=>model.Test)
<div class="row">
<div class="col-md-2">
#Html.LabelFor(model => model.Incident.IncidentDateTime)
</div>
<div class="col-md-2">
#Html.DisplayFor(model => model.Incident.IncidentDateTime)
</div>
</div>
<div class="row">
<div class="col-md-2">
#Html.LabelFor(model => model.Incident.Description)
</div>
<div class="col-md-10">
#Html.EditorFor(model => model.Incident.Description, new { htmlAttributes = new { #class = "form-control", rows = "5" }, })
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.Incident.FollowUpDate)
</div>
<div class="col-md-2">
#Html.EditorFor(model => model.Incident.FollowUpDate, new { htmlAttributes = new { #class = "form-control"}, })
</div>
</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>
}
The problem is that the DefaultModelBinder won't be able to map nested models properly if you use a different parameter name. You must use the same parameter name as the ViewModel name.
public ActionResult Create(IncidentManager incidentManager)
As a general practice, always use the name of the model as the parameter name to avoid mapping problems.
UPDATE:
The DefaultModelBinder uses "convention based" mapping.
IncidentManager.Incident = incidentManager.Incident (will map)
IncidentManager.Incident = im.Incident //won't map because 'im' != 'incidentManager'

Uploading multiple files asp.net mvc4 in a single form

I am trying to upload multiple files in one form and I have tried different ways.
This is my model
[MetadataType(typeof(MovieMetadata))]
public partial class Movie
{
}
class MovieMetadata
{
[ScaffoldColumn(false)]
public int id { get; set; }
[Required(ErrorMessage = "Title is required")]
public string title { get; set; }
[Required]
public DateTime releaseDate { get; set; }
public string storyline { get; set; }
public Binary poster { get; set; }
[ScaffoldColumn(false)]
public DateTime? duration { get; set; }
[ScaffoldColumn(false)]
public Binary trailer { get; set; }
}
One of the files that I want to upload is a video, so I put this tag in my Web.config to upload a file less than 1 GB, I put a big number because I will not know the size of the video
<httpRuntime targetFramework="4.5" maxRequestLength="102400"/>
My Controller is the following:
[HttpPost]
public ActionResult Create(Movie movie)
{
if (ModelState.IsValid)
{
//saving the movie
OperationStatus opStatus = Repository.Save(movie);
if (!opStatus.Status)
{
return View("Error");
}
}
return View(movie);
}
Here is my View:
#model MoviesModel.Movie
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/MoviesLayout.cshtml";
}
#section createMovie{
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "createForm", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="gallMemberBox">
<div class="leftFormContent">
Movie Name
<div class="imgTmpl">
<!--solo hay que especificar el src de la imagen-->
<img src="../../Content/img/imgTest.jpg" alt="" />
</div>
</div>
<div class="rightFormContent">
<div>
#Html.LabelFor(model => model.title)
#Html.EditorFor(model => model.title)
#Html.ValidationMessageFor(model => model.title)
</div>
<div>
#Html.LabelFor(model => model.releaseDate)
#Html.EditorFor(model => model.releaseDate)
#Html.ValidationMessageFor(model => model.releaseDate)
</div>
<div>
#Html.LabelFor(model => model.duration)
<div>
<input type="text" id="time1" size="10" />
</div>
<pre><code></code></pre>
</div>
<div>
#Html.Label("Poster")
<input name="poster" value="C:" id="poster" type="file" />
</div>
<div>
#Html.Label("Trailer")
<input name="trailer" value="" id="trailer" type="file" />
</div>
<div>
#Html.LabelFor(model => model.storyline)
<textarea id="storyline"></textarea>
</div>
<input type="submit" value="Create" />
</div>
<div class="clearBoth"></div>
</div>
}
}
#section scripts{
#Scripts.Render("~/Scripts/jquery.timePicker.js")
<script type="text/javascript">
jQuery(function ()
{
// Default.
$("#time1").timePicker(
{
startTime: "00.00",
endTime: new Date(0, 0, 0, 6, 30, 0),
show24Hours: true,
separator: ':',
step: 3
}
);
})
</script>
}
#section styles{
#Styles.Render("~/Content/timePicker.css")
}
This includes the timepicker.js and css(inside the section style). Start time is to display the first option of time to select, the hour 00:00 and end time was 06:30, show24hours option hides from the control am and pm format, step: 3 means that the control will have all the hours in with the previous format with .3 minutes of difference. The sequence is like this: 00:00 00:03 00:06.... 06:27 06:30. I took it from this site https://github.com/perifer/timePicker/blob/master/index.htm
The problem is the following, when I tried to submit my form with all data(including the fields that are not required, first I got this message:
The input is not a valid Base-64 string as it contains a non-base 64
character, more than two padding characters, or an illegal character
among the padding characters.
I resolved it with this code:
public ActionResult Create([Bind(Exclude = "poster, trailer")]Movie movie, HttpPostedFileBase poster, HttpPostedFileBase trailer)
So I excluded poster and trailer field and I passed them to the controller like HttpPostedFileBase, thats work but my ModelState.IsValid is false. I thought that it could be a problem of my timepicker, so I excluded the duration field from the View and I tried again, and again I got false. I tried to put use this:
public ActionResult Create(FormCollection formCollection)
and with the post just came two keys, title and releaseDate. What about the others? What about ModelState.IsValid with the false value? Can I resolve my problem with a strong type and without the HttpPostedFileBase extra parameters that I put in the Create method of the controller?(Something like this: )
public ActionResult Create(Movie movie)
with the posted files included inside of it?

Asp.net mvc Edit Page what can I use besides .Entry?

I adding an admin area to an Asp.net MVC4 Application and I would consider myself a entry-level developer. My edit [HttpGet] action is working fine as it returns the values of asset. I have poured through a bunch of MVC4 specials online and most of them use the following for [HttpPost] Edit method:
[HttpPost]
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
_entities.Entry(models).State = EntityState.Modified;
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
The problem is that I do not have access to use .Entry in the following:
_entities.Entry(models).State = EntityState.Modified;
I am obviously missing a reference that will enable me to use it, but I am not sure what it is.
Here is my ViewModel(I would have used DbContext, but they did not):
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using ITTESI.AssetTracker.Web.UI.Content.Classes;
namespace ITTESI.AssetTracker.Web.UI.ViewModels
{
public class AssetDetailsViewModel
{
public int ID { get; set; }
public string AssetIdentifier { get; set; }
public string ManufacturerName { get; set; }
public string Model { get; set; }
public string SchoolLocation { get; set; }
public string Status { get; set; }
public string Condition { get; set; }
// [DataType(DataType.MultilineText)]
public string Notes { get; set; }
public Utils.AssignReturn AssignReturnEligible { get; set; }
public string SchoolLocationCd { get; set; }
public string SchoolLocationDisplayValue { get; set; }
public AssignedUserViewModel AssignedUserViewModelObj { get; set; }
}
}
Here is my Admin Controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using ITTESI.AssetTracker.Data.EntityModel.Entity;
using ITTESI.AssetTracker.Data.EntityModel.Definition;
using System.Data.Entity;
using ITTESI.AssetTracker.Web.UI;
using ITTESI.AssetTracker.Web.UI.Content;
using ITTESI.AssetTracker.Web.UI.Content.Classes;
using ITTESI.AssetTracker.Web.UI.ViewModelBuilders;
using ITTESI.AssetTracker.Web.UI.ViewModels;
namespace ITTESI.AssetTracker.Web.UI.Controllers
{
public class AdminController : Controller
{
ExtendedITTESI_AssetTrackerEntities _entities = new ExtendedITTESI_AssetTrackerEntities();
public ActionResult Index(ViewModels.AssetDetailsViewModel assetDetails)
{
ViewBag.PageTitle = "Admin Search";
ViewBag.HideShowLocation = "hide";
ViewBag.SubmitButtonValue = "Search";
return View("Index", assetDetails);
}
[HttpGet]
public ActionResult Edit(ITTESI_AssetTracker_Asset asset) // 'ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel'
{
ViewBag.PageTitle = "Edit Asset";
ViewBag.SubmitButtonValue = "Save";
ViewBag.ShowLocation = true;
var model = _entities.ITTESI_AssetTracker_Asset.FirstOrDefault();
return View(model);
}
[HttpPost]
//public ActionResult Edit(ExtendedITTESI_AssetTrackerEntities ate)
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
_entities.Entry(models).State = EntityState.Modified;
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
}
}
Here is my Edit View:
#model ITTESI.AssetTracker.Data.EntityModel.Entity.ITTESI_AssetTracker_Asset
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>ITTESI_AssetTracker_Asset</legend>
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.AssetIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetIdentifier)
#Html.ValidationMessageFor(model => model.AssetIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetConditionID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetConditionID)
#Html.ValidationMessageFor(model => model.AssetConditionID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SchoolID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SchoolID)
#Html.ValidationMessageFor(model => model.SchoolID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetCategoryID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetCategoryID)
#Html.ValidationMessageFor(model => model.AssetCategoryID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.VendorID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.VendorID)
#Html.ValidationMessageFor(model => model.VendorID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssignedPersonID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssignedPersonID)
#Html.ValidationMessageFor(model => model.AssignedPersonID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetStatusID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetStatusID)
#Html.ValidationMessageFor(model => model.AssetStatusID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ManufacturerID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ManufacturerID)
#Html.ValidationMessageFor(model => model.ManufacturerID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModelDetail)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModelDetail)
#Html.ValidationMessageFor(model => model.ModelDetail)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CreatedOn)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CreatedOn)
#Html.ValidationMessageFor(model => model.CreatedOn)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CreatedByIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CreatedByIdentifier)
#Html.ValidationMessageFor(model => model.CreatedByIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModifiedOn)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModifiedOn)
#Html.ValidationMessageFor(model => model.ModifiedOn)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModifiedByIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModifiedByIdentifier)
#Html.ValidationMessageFor(model => model.ModifiedByIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Notes)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Notes)
#Html.ValidationMessageFor(model => model.Notes)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I also certain the problem is that DbContext for ExtendedITTESI_AssetTrackerEntities does not exist and after research a bit more that is part of the System.Data.Entity. The only code I have for ExtendedITTESI_AssetTrackerEntities is:
using System;
using Common.Logging;
using EFCachingProvider;
using EFCachingProvider.Caching;
using EFProviderWrapperToolkit;
using EFTracingProvider;
using ITTESI.AssetTracker.Data.EntityModel.Entity;
namespace ITTESI.AssetTracker.Data.EntityModel.Definition
{
public class ExtendedITTESI_AssetTrackerEntities : ITTESI_AssetTrackerEntities
{
private ILog logOutput;
public ExtendedITTESI_AssetTrackerEntities()
: this("name=ITTESI_AssetTrackerEntities")
{
}
public ExtendedITTESI_AssetTrackerEntities(string connectionString)
: base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
connectionString,
"EFTracingProvider",
"EFCachingProvider"
))
{
CachingPolicy = AssetTrackerEntitiesCachingPolicy.CachingPolicy();
Cache = AssetTrackerEntitiesCache.Cache();
}
#region Tracing Extensions
private EFTracingConnection TracingConnection
{
get { return this.UnwrapConnection<EFTracingConnection>(); }
}
public event EventHandler<CommandExecutionEventArgs> CommandExecuting
{
add { this.TracingConnection.CommandExecuting += value; }
remove { this.TracingConnection.CommandExecuting -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFinished
{
add { this.TracingConnection.CommandFinished += value; }
remove { this.TracingConnection.CommandFinished -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFailed
{
add { this.TracingConnection.CommandFailed += value; }
remove { this.TracingConnection.CommandFailed -= value; }
}
private void AppendToLog(object sender, CommandExecutionEventArgs e)
{
if (this.logOutput != null)
{
this.logOutput.Debug(e.ToTraceString().TrimEnd());
}
}
public ILog Log
{
get { return this.logOutput; }
set
{
if ((this.logOutput != null) != (value != null))
{
if (value == null)
{
CommandExecuting -= AppendToLog;
}
else
{
CommandExecuting += AppendToLog;
}
}
this.logOutput = value;
}
}
#endregion
#region Caching Extensions
private EFCachingConnection CachingConnection
{
get { return this.UnwrapConnection<EFCachingConnection>(); }
}
public ICache Cache
{
get { return CachingConnection.Cache; }
set { CachingConnection.Cache = value; }
}
public CachingPolicy CachingPolicy
{
get { return CachingConnection.CachingPolicy; }
set { CachingConnection.CachingPolicy = value; }
}
#endregion
}
}
I might have to create a model with DbContext is that fair to say?
Can I use anything besides .Entry? I appreciate the help, but with the way the app is set up I am not sure how to properly save edits back to the database.
there is a way besides .Entry for the Edit Action. EF is very clever, you can just fetch the object by ID form the database and change all the properties manually.
Ex:
[HttpPost]
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel temp = _entities.dbname.firstOrDefault(x = > x.ID == models.ID);
temp.AssetIdentifier = models.AssetIdentifier ;
temp.ManufacturerName = models.ManufacturerName ;
.
.
.
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
EF will understand what entity you want to modify, and will update it with "_entities.saveChanges();"
I don't really know that this will work for you, but I think it's worth trying

Remote Validate for DropDownList, MVC3, not firing in my case

I am using ASP.NET MVC3 and EF 4.1
I have two DropDownList in my Model, It is required and not duplicated too.
And I want the Remote validate function: ValidateDuplicateInsert get firing when user submit data. But I can NOT get the ValidateDuplicateInsert function firing.
Where am I wrong?
My Model
[Key]
public int CMAndOrgID { get; set; }
[Display(Name = "CM")]
[Required(ErrorMessage = "CM is required.")]
[Remote("ValidateDuplicateInsert", "CMAndOrg", HttpMethod = "Post", AdditionalFields = "CMID, OrganizationID", ErrorMessage = "CM is assigned to this Organization.")]
public int? CMID { get; set; }
[Display(Name = "Organization")]
[Required(ErrorMessage = "Organization is required.")]
public int? OrganizationID { get; set; }
public virtual CM CM { get; set; }
public virtual Organization Organization { get; set; }
The ValidateDuplicateInsert function in my CMAndOrg controller
[HttpPost]
public ActionResult ValidateDuplicateInsert(string cmID, string orgID)
{
bool flagResult = true;
foreach (CMAndOrg item in db.CMAndOrgs)
{
if (item.CMID.ToString() == cmID && item.OrganizationID.ToString() == orgID)
{
flagResult = false;
break;
}
}
return Json(flagResult);
}
And my View
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>CMAndOrg</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CMID, "CM")
</div>
<div class="editor-field">
#Html.DropDownList("CMID", String.Empty)
#Html.ValidationMessageFor(model => model.CMID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OrganizationID, "Organization")
</div>
<div class="editor-field">
#Html.DropDownList("OrganizationID", String.Empty)
#Html.ValidationMessageFor(model => model.OrganizationID)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
There is a bug in MVC3 related to unobtrusive validation on dropdownlist. Please reference to this http://aspnet.codeplex.com/workitem/7629[^] link for more detail explaination.
Briefly, you can't use the same name for category collection and category field, so just change your collection name and update following line in your view
#Html.DropDownList("CategoryID", String.Empty)
with this
#Html.DropDownListFor(model => model.CategoryID, new SelectList((System.Collections.IEnumerable)ViewData["Categories"], "Value", "Text"))
Thanks again Henry He
Original link
http://www.codeproject.com/Articles/249452/ASP-NET-MVC3-Validation-Basic?msg=4330725#xx4330725xx

ASP.NET MVC 3 login page by using partial

I want to use Logon page in on home page partially (which is index page).
Then my homepage has UserName textbox, Password textbox , RememberMe checkbox and button for login and register which means Logon page is partial view.
When I run the homepage and if I click Login button, it does not work validation error even
I linked JavaScript and I put [Required] on model class.
I don't know how can I enable the validation error with JavaScript?
And how can I use the HomeController? (Homepage is default page)
Could you help me?
I am beginner, and I am just started to develop MVC application.
Index.cshtml on Home folder
<div id="border_frame">
#Html.Partial("_LogOnPartial")
</div>
LogonPartial.cshtml on Shared folder
#model MvcApplication2.Models.LogOnModel
#if (Request.IsAuthenticated)
{
<text>Welcome <strong>#User.Identity.Name</strong>!
[ #Html.ActionLink("Log Off", "LogOff", "Account") ]</text>
}
else
{
<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())
{
<div>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName, new { style = "width:150px;" })
#Html.ValidationMessageFor(m => m.UserName)
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password, new { style = "width:150px;" })
#Html.ValidationMessageFor(m => m.Password)
<div>
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe)
</div>
<button name="button" class="login_button" value="logIn">Log In</button>
<button name="button" class="register_button" value="register">Register now</button>
</div>
#Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
}
}
AccountModel.cs
public class LogOnModel
{
[Required]
[Display(Name = "User ID")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
HomeController.cs
public ActionResult Index()
{
return View();
}
You have to have a post action method to handle your postback.
[HttpPost]
public ActionResult Index(LogonModel model)
{
if (ModelState.IsValid) {
// do your validation stuff
}
// If you don't return the model, validation won't work.
return View(model);
}

Resources