Model Validation With MVC Razor - c#

I'm implementing MVC based website using the Razor engine.
I have created the validation to be in the model.
i.e. Student validation is like this:
[MetadataType(typeof(Student.StudentMetaData))]
public partial class Student
{
internal sealed class StudentMetaData
{
[Required(ErrorMessageResourceName = "FirstNameRequired", ErrorMessageResourceType = typeof(StudentMessages))]
public object FirstName { set; get; }
[Required(ErrorMessageResourceName = "FatherNameRequired", ErrorMessageResourceType = typeof(StudentMessages))]
public object FatherName { set; get; }
}
}
The student already implements the IDataErrorInfo interface. The data fields exist in the other partial class (the partial class created by T4 file).
The problem is when I use it with client validation in Razor view using:
#Html.TextBoxFor(m => m.FatherName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.FatherName)
it doesn't get the messages I specified in my resource files.
I have tried the same technique before with WPF and it works just fine.
I allowed the client validation in the Web.config and used this in my view:
#{
HtmlHelper.ClientValidationEnabled = true;
}

Add Name space in modal class in mvc.
using System.ComponentModel.DataAnnotations;
public class TelePhones
{
[Required (ErrorMessage = "MobileNo is required")]
public long MobileNo { get; set; }
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
[DataType(DataType.Date)]
public string DateOfBirth { get; set; }
[Range(15, 70, ErrorMessage = "Price must be between 15 and 70")]
public int Age { get; set; }
}
client side validation in mvc
<div class="editor-label">
#Html.LabelFor(model => model.MobileNo)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MobileNo)
#Html.ValidationMessageFor(model => model.MobileNo)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DateOfBirth)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DateOfBirth)
#Html.ValidationMessageFor(model => model.DateOfBirth)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Age)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Age)
#Html.ValidationMessageFor(model => model.Age)
</div>

Related

Cannot Save record to DB to to SelectListItem Error - Razor C#

I have created a strongly typed view using visual studio and have added some dropdownlists for the user to select an option from a connected database table column but these dropdownlists seem to cause some issues. I keep getting the errors below and I am not sure why. These drop downs should be saving the options as a string to corresponding item record. Not sure why it is looking for a key named AssignedTo. Any suggestions? All help is much appreciated.
Error Message:
There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'AssignedTo'.
Source Error:
Line 34: </div>
Line 35: <div class="editor-field">
Line 36: #Html.DropDownListFor(model => model.AssignedTo, (SelectList)ViewBag.AssignedToList)
Line 37: #Html.ValidationMessageFor(model => model.AssignedTo)
Line 38: </div>
Here is my strongly typed Create View:
#model ApIssues.Models.AP_Tasks
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Issue</legend>
<div class="editor-label">
#Html.LabelFor(model => model.TaskDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.TaskDate)
#Html.ValidationMessageFor(model => model.TaskDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.InvDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.InvDate)
#Html.ValidationMessageFor(model => model.InvDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssignedTo)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.AssignedTo, (SelectList)ViewBag.AssignedToList)
#Html.ValidationMessageFor(model => model.AssignedTo)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CC)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.CC, (SelectList)ViewBag.CcToList)
#Html.ValidationMessageFor(model => model.CC)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Whse)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Whse, (SelectList)ViewBag.WarehouseList)
#Html.ValidationMessageFor(model => model.Whse)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PO)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PO)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FreightNo)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FreightNo)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.VendName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.VendName)
#Html.ValidationMessageFor(model => model.VendName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ReqCompDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ReqCompDate)
#Html.ValidationMessageFor(model => model.ReqCompDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.TaskType)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.TaskType)
#Html.ValidationMessageFor(model => model.TaskType)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Here is my model:
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.Validation;
namespace ApIssues.Models
{
using System;
using System.Collections.Generic;
public partial class AP_Tasks
{
[Required]
public int TaskID { get; set; }
[DataType(DataType.DateTime)]
[Display(Name = "Task Date")]
public Nullable<System.DateTime> TaskDate { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Task Type")]
public string TaskType { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Assigned By")]
public string AssignedBy { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Assigned To")]
public string AssignedTo { get; set; }
[DataType(DataType.Text)]
[Display(Name = "CC")]
public string CC { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Warehouse")]
public string Whse { get; set; }
[DataType(DataType.Text)]
[Display(Name = "PO #")]
public string PO { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Freight #")]
public string FreightNo { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Vendor Name")]
public string VendName { get; set; }
[DataType(DataType.DateTime)]
[Display(Name = "Req. Complete Date")]
public Nullable<System.DateTime> ReqCompDate { get; set; }
[DataType(DataType.DateTime)]
[Display(Name = "Due Date")]
public Nullable<System.DateTime> DueDate { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Completion Date")]
public Nullable<System.DateTime> CompDate { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Notes Summary")]
public string Notes { get; set; }
[DataType(DataType.DateTime)]
[Display(Name = "Invoice Date")]
public Nullable<System.DateTime> InvDate { get; set; }
[Display(Name = "Company Number")]
public Nullable<int> CoNo { get; set; }
[Display(Name = "Note Count")]
public Nullable<int> NoteCnt { get; set; }
}
}
Here is my Action:
[HttpGet]
public ActionResult Create()
{
//TODO: Add drop down lists
//TODO: Change the Cono in Query1
var nxtDb = new nxtSQLEntities();
var whses = from w in nxtDb.icsds select w.whse;
var warehouseList = new SelectList(whses);
ViewBag.WarehouseList =
warehouseList;
var userDb = new PDDAEntities1();
var query1 = from u in userDb.Users where u.Cono == 1 select new {u.UserName, u.FirstName, u.LastName};
var query2 = from gm in userDb.GroupMembers
join ug in userDb.UserGroups on gm.GroupID equals ug.GroupID
join u in userDb.Users on gm.UserName equals u.UserName
where ug.GroupName == "AP Department" || ug.GroupName == "MIS"
orderby new {u.LastName, u.FirstName}
select new {UserName = u.UserName, FirstName = u.FirstName, LastName = u.LastName};
var query3 = query1.Concat(query2);
var results = new List<string>{};
results.AddRange(query3.Select(entry => entry.UserName));
ViewBag.AssignedToList = new SelectList(results);
ViewBag.CcToList = new SelectList(results);
return View();
}
[HttpPost]
public ActionResult Create(AP_Tasks task)
{
// Save an task to the database
var db = new Accounting_AaronTestEntities();
try
{
db.AP_Tasks.Add(task);
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);
}
}
return View();
}
return RedirectToAction("Index");
}
Anyone know why I am getting this error?
Try it this way.
#Html.DropDownListFor(model => model.AssignedTo,
new SelectList(ViewBag.AssignedToList, "Id", "AssignedTo"), "---Select Assigner---", new { ID = "ddlAssigned" })
Hope it helps.
try variants of the top two answers here:
Having difficulty using an ASP.NET MVC ViewBag and DropDownListfor

Controller unwantedly creates new user in database

On my MVC4 application I have a page where an user can be placed in a schedule. The idea is that you can select a person and that they will be entered on the schedule. The Schedule Model looks as follows:
public class Schedule {
[Key]
public int scheduleId { get; set; }
[Column(TypeName = "Date")]
[DataType(DataType.Date)]
public DateTime date { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
}
The User Model where the Schedule Model refers to looks like this:
public class User {
public int UserId { get; set; }
[Display(Name = "Naam")]
public string Name { get; set; }
public string Email { get; set; }
[Display(Name = "Beschikbaar")]
public bool isAvailable { get; set; }
}
An user can be placed on the scheduling page with the following controller:
public ActionResult Create(Schedule schedule)
{
if (ModelState.IsValid)
{
db.Schedules.Add(schedule);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(schedule);
}
The Schedule/Create view looks like this:
and has the following code:
<h2>Schedule a person</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Schedule</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserId)
</div>
<div class="editor-field">
#Html.DropDownList("UserId", String.Empty)
#Html.ValidationMessageFor(model => model.UserId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.date)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.date)
#Html.ValidationMessageFor(model => model.date)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.isAvailable)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.User.isAvailable)
#Html.ValidationMessageFor(model => model.User.isAvailable)
</div>
<p>
<input type="submit" value="Plan" />
</p>
</fieldset>
}
This code does place the user on the schedule on the specified date. But somehow an extra "null" user is created in the database every time an existing user is added to the schedule. See this image:
I have been breaking my head over this unwanted behaviour for the past hours. The Create action of the ScheduleController does not specify to create an extra user. I have no idea why it does do so anyway.
Does anyone here have any idea?
It's because of your .User.IsAvailabe property. This creates a new user when adding the schedule.
You'll have to attach the existing user to your schedule. Perhaps you can even get rid of UserId and use User.Id in your form.

Why does this not display the display name?

I'm trying to display the displaynames for the properties in my html in my ASP.NET MVC 4 application.
However even though I've set the displaynames in the viewmodel the raw variable names still gets displayed instead.
The viewmodel:
public class Manage_ManagePasswordViewModel
{
[Display(Name="Name")]
public string name;
[Display(Name = "SubID")]
public string subId;
[Display(Name = "Conversions")]
public int conversions;
[Display(Name = "Password")]
public string password;
public UserProfile owner;
public Manage_ManagePasswordViewModel(ProtectedPassword pw)
{
name = pw.Name;
subId = pw.SubId;
conversions = pw.GetConversions();
password = pw.Password;
owner = pw.Owner;
}
}
The cshtml file:
#model Areas.Admin.Models.ViewModels.Manage_ManagePasswordViewModel
<div class="editor-label">
#Html.DisplayNameFor(m => m.name):
#Html.DisplayTextFor(m => m.name)
</div>
<div class="editor-label">
#Html.DisplayNameFor(m => m.password):
#Html.DisplayTextFor(m => m.password)
</div>
<div class="editor-label">
#Html.DisplayNameFor(m => m.subId):
#Html.DisplayTextFor(m => m.subId)
</div>
<div class="editor-label">
#Html.DisplayNameFor(m => m.conversions):
#Html.DisplayTextFor(m => m.conversions)
</div>
<div class="editor-label">
#Html.DisplayNameFor(m => m.owner.UserName):
#Html.UserLink(Model.owner.UserName, Model.owner.UserId)
</div>
Use properties instead of fields, for ex.
[Display(Name="Name")]
public string name {get;set;}

Fill in form based on dropdown selection (MVC 4)

I am using asp.net mvc 4
Is there a way to update the form based on selection made by the user?
(in this case I want to fill in address fields if something is picked from the dropdown list, otherwise a new address would need to be typed in)
My model:
public class NewCompanyModel
{
[Required]
public string CompanyName { get; set; }
public bool IsSameDayRequired { get; set; }
public int AddressID { get; set; }
public Address RegisterOfficeAddress { get; set; }
}
View:
#model ViewModels.NewCompanyModel
#using (Html.BeginForm(null, null, FormMethod.Post, new { name = "frm", id = "frm" }))
{
#Html.ValidationSummary(true)
<fieldset id="test">
<legend>Company</legend>
<h2>Register office address</h2>
<div class="editor-label">
#Html.LabelFor(model => model.AddressID)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.AddressID, (IList<SelectListItem>)ViewBag.Addresses, new {id = "address", onchange = "window.location.href='/wizard/Address?value=' + this.value;" })
</div>
<div class="editor-label">
#Html.LabelFor(model => model.RegisterOfficeAddress.BuildingNameOrNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.RegisterOfficeAddress.BuildingNameOrNumber)
#Html.ValidationMessageFor(model => model.RegisterOfficeAddress.BuildingNameOrNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.RegisterOfficeAddress.StreetName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.RegisterOfficeAddress.StreetName)
#Html.ValidationMessageFor(model => model.RegisterOfficeAddress.StreetName)
</div>
and controller:
public ActionResult Address(string value)
{
//get the address from db and somehow update the view
}
The question is how do you update the 'model.RegisterOfficeAddress.StreetName' etc
Just to make clear this is just part of the form so I cannot submit it just yet.
Many thanks
Thanks for your help; I have decided to take a different approach:
On dropdown change I submit the form:
<div class="editor-label">
#Html.LabelFor(model => model.ServiceAddress.AddressID)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ServiceAddress.AddressID, (IEnumerable<SelectListItem>)ViewBag.Addresses, new { onchange = "this.form.submit();" })
#Html.ValidationMessageFor(model => model.ServiceAddress.AddressID)
</div>
and then in controller:
[HttpPost]
public ActionResult NewDirector(NewDirectorVM vm, string value)
{
ModelState.Clear();
if (vm.ServiceAddress.AddressID > 0)
{
//Updates the properties of the viewModel
vm.ServiceAddress = _Repository.GetAddress(vm.ServiceAddress.AddressID);
}
return View("NewDirector", vm);
}
Please notice ModelState.Clear(); which actually allows the view to be updated from the controller (otherwise all the changes made the the viewModel by the controller would have been overwritten by the values in the view).
Common way in such cases is to update other fields via javascript:
$('##Html.IdFor(model => model.AddressID)').on('change',function(){
$.get(...,function(data){
$('##Html.IdFor(model => model.RegisterOfficeAddress.BuildingNameOrNumber)').val(data)
})
})

Email Form with MvcMailer

I am developing an MVC 3 application and I am sending emails using MvcMailer.I am able to send basic emails, but I am trying to email the contents of a form and can't seem to work it out.
Here is the code for my model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace DFPProductions_Default.Models
{
public class Application
{
[Required]
[Display(Name = "First Name")]
public string ApplicantFirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string ApplicantLastName { get; set; }
[Display(Name = "Birth Date")]
public DateTime ApplicantBirthDate { get; set; }
[Required]
[Display(Name = "Cellphone Number")]
public string ApplicantCellphoneNumber { get; set; }
[Display(Name = "Postal Address")]
public string PostalNumber { get; set; }
[Display(Name = "Suburb")]
public string ApplicantSuburb { get; set; }
[Display(Name = "City")]
public string ApplicantCity { get; set; }
[Display(Name = "Post Code")]
public string ApplicationPostalCode { get; set; }
[Required]
[Display(Name = "Email Address")]
public string ApplicantEmailAddress { get; set; }
[Display(Name = "First Name")]
public string ParentFirstName { get; set; }
[Display(Name = "Last Name")]
public string ParentLastName { get; set; }
[Display(Name = "Email Address")]
public string ParentEmailAddress { get; set; }
[Display(Name = "Postal Address")]
public string ParentPostalNumber { get; set; }
[Display(Name = "Suburb")]
public string ParentSuburb { get; set; }
[Display(Name = "City")]
public string ParentCity {get; set;}
[Display(Name = "Post Code")]
public string ParentPostalCode {get; set;}
}
}
In my view, I have editor fields, here are a few:
<div class="editor-label">
#Html.LabelFor(model => model.ApplicantFirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicantFirstName)
#Html.ValidationMessageFor(model => model.ApplicantFirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicantLastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicantLastName)
#Html.ValidationMessageFor(model => model.ApplicantLastName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicantBirthDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicantBirthDate)
#Html.ValidationMessageFor(model => model.ApplicantBirthDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicantCellphoneNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicantCellphoneNumber)
#Html.ValidationMessageFor(model => model.ApplicantCellphoneNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicantEmailAddress)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicantEmailAddress)
#Html.ValidationMessageFor(model => model.ApplicantEmailAddress)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PostalNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PostalNumber)
#Html.ValidationMessageFor(model => model.ApplicantEmailAddress)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicantSuburb)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicantSuburb)
#Html.ValidationMessageFor(model => model.ApplicantSuburb)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicantCity)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicantCity)
#Html.ValidationMessageFor(model => model.ApplicantCity)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicationPostalCode)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicationPostalCode)
#Html.ValidationMessageFor(model => model.ApplicationPostalCode)
</div>
</div>
I have called the email Application. The code for ApplicationMailer is:
public virtual MailMessage Application()
{
var mailMessage = new MailMessage{Subject = "Application"};
mailMessage.To.Add("debbie#gmail.com");
ViewBag.Data = "Debbie";
PopulateBody(mailMessage, viewName: "Application");
return mailMessage;
}
I have this in my controller:
private IApplicationMailer _applicationMailer = new ApplicationMailer();
public IApplicationMailer ApplicationMailer
{
get { return _applicationMailer; }
set { _applicationMailer = value; }
}
public ActionResult SendApplication()
{
ApplicationMailer.Application().Send();
//Send() extension method: using Mvc.Mailer
return RedirectToAction("Index");
}
And all I've added to the view of the email is
#model DFPProductions_Default.Models.Application
The email sends, so it is configured correctly, but I'm really not sure how to retrieve the values inserted into the form in the email view.
Thanks,
Amy
You need to utilize your model class data in the controller something like this:
public virtual MailMessage Application(ModelNameHere model)
{
var mailMessage = new MailMessage{Subject = "Application"};
mailMessage.To.Add("debbie#gmail.com");
//add field from your view here
string body = model.CellPhoneNumber + Model.FirstName;
ViewBag.Data = "Debbie";
PopulateBody(mailMessage, viewName: "Application", body);
return mailMessage;
}

Categories