DropDownListFor selection not being saved - asp.net-mvc

I am new to MVC. I am using a DropDownListFor to display a list of company names and, based on the selection made, filling in other Customer fields. The customer fields are being populated fine, but when I attempt to POST the record, I get a validation error "Company name is required", even though the company name has been selected in the DropDownListFor. Here is the ViewModel:
namespace CMSUsersAndRoles.Models
{
public class QuoteViewModel
{ [Key]
[Display(Name = "Quote Id")]
public int QuoteId { get; set; }
// Columns from Customer table
[Required(ErrorMessage = "Please select a company")]
[Display(Name = "Customer Id")]
public int? CustomerId { get; set; }
[Display(Name = "Sales Rep")]
public string SalesRep { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
public string Company { get; set; }
[Display(Name = "Address 1")]
public string Address1 { get; set; }
[Display(Name = "Address 2")]
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
[StringLength(10)]
[Display(Name = "Zip Code")]
[RegularExpression(#"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid Zip Code")]
public string PostalCode { get; set; }
[Phone]
[Display(Name = "Work Phone")]
public string WorkPhone { get; set; }
[Phone]
[Display(Name = "Cell Phone")]
public string CellPhone { get; set; }
[EmailAddress]
public string Email { get; set; }
[Range(0, 100)]
public decimal? Discount { get; set; }
[Display(Name = "Payment Terms")]
public int? PaymentTerms { get; set; }
// Columns from QuoteDetail table
[Display(Name = "Quote Detail")]
public List<QuoteDetail> QuoteDetail { get; set; }
// Columns from Quote table
public decimal Subtotal { get; set; }
public decimal Tax { get; set; }
public decimal Total { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Quote Date")]
public DateTime? QuoteDate { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Good Until")]
public DateTime? GoodUntil { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Quote Sent")]
public DateTime? QuoteSent { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Date Approved")]
public DateTime? DateApproved { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Date Ordered")]
public DateTime? DateOrdered { get; set; }
}
}
Here is the code from the View:
#Html.DropDownListFor(model => model.CustomerId, new SelectList(ViewBag.Customers, "CustomerId", "Company"), "---Select one---", new { htmlAttributes = new { #class = "company" } });
#Html.HiddenFor(model => model.Company)
#Html.ValidationMessageFor(model => model.Company, "", new { #class = "text-danger" })
Here is the Get:
public ActionResult Create()
{
QuoteViewModel qvm = new QuoteViewModel();
var customers = db.Customers.ToList();
ViewBag.Customers = customers;
return View(qvm);
}
And here is the code for the POST:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(QuoteViewModel qvm)
{
if (ModelState.IsValid)
{
Quote quote1 = new Quote();
quote1.CustomerId = qvm.CustomerId;
...
customer.CustomerId = (int)qvm.CustomerId;
...
customer.Company = qvm.Company;
db.Entry(customer).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
var objContext = ((IObjectContextAdapter)db).ObjectContext;
// Get failed entry
var entry = ex.Entries.Single();
// Now call refresh on ObjectContext
objContext.Refresh(RefreshMode.ClientWins, entry.Entity);
}
return RedirectToAction("Index");
}
var customers = db.Customers.ToList();
ViewBag.Customers = customers;
return View(qvm);
}
What am I missing? Any help will be much appreciated.

I was not setting the value of the HiddenFor below. Thanks, #StephenMuecke.
#Html.HiddenFor(model => model.Company)

Related

ASP.NET MVC5. Error code not allowing controller to be view in browser

HAVING TROUBLE GETTING MY EVENTS CONTROLLER TO SHOW IN BROWSER. I AM RECEIVING ERROR MESSAGE THAT MY COLUMN NAME IS INVALID
SqlException: Invalid column name 'City'.
Invalid column name 'State'.
EVENT MODEL code
public class Events
{
[Key]
public int EventsId { get; set; }
[Required(ErrorMessage = "Title is requied")]
[StringLength(50, ErrorMessage = "Title cannot be more than 50 characters")]
public string EventTitle { get; set; }
[StringLength(150, ErrorMessage = "Description should not exceed 150 characters")]
public string EventDescription { get; set; }
[Required]
public DateTime EventStartTime { get; set; }
[Required(ErrorMessage = "Start Date cannot be in the past")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0;MMdd/yyyy}")]
public DateTime EventStartDate { get; set; }
[Required]
public DateTime EventEndTime { get; set; }
[Required(ErrorMessage = "End date cannot be less than Start date")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0;MMdd/yyyy}")]
public DateTime EventEndDate { get; set; }
public string City { get; set; }
public string State { get; set; }
public string EventType { get; set; }
[Required]
public string OrganizerName { get; set; }
public string OrganizerContactInfo { get; set; }
[Required(ErrorMessage = " Max tickets cannot be 0")]
public int MaxTickets { get; set; }
[Required(ErrorMessage = "Avaliable tickets cannot be 0")]
public int AvaliableTickets { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
throw new NotImplementedException();
}
}
}
here
enter image description here
There is a lot of information missing. My guess would be the Events table in your database does not contain City or State columns.

A specified Include path is not valid on eager loading

I am using eager loading in entity framework. My Model class is like
public class EmployeeMaster : AbsCommonParameters
{
[Key]
public int Id { get; set; }
public string EmpId { get; set; }
[Required(ErrorMessage = "Employee name is required")]
public string Name { get; set; }
[Required(ErrorMessage = "Employee geography is required")]
public string Geography { get; set; }
public string EmailId { get; set; }
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
[Column(TypeName = "Date")]
[Display(Name = "Date Of Joining")]
public Nullable<DateTime> DOJ { get; set; }
[Required(ErrorMessage = "Employee designation is required")]
public string Designation { get; set; }
[NotMapped]
public List<CenterMaster> lstCenters { get; set; }
[NotMapped]
public List<CostCodeMaster> lstCostCode { get; set; }
}
In Controller Index Action my Code is like this
public ActionResult Index()
{
var lstUser = db.ObjEmployeeMaster.Include(p => p.lstCenters).
Include(p => p.lstCostCode).Where(x => x.DeletedStatus == false).ToList();
return View(lstUser);
}
Also In DBContext Constructor I have used
this.Configuration.LazyLoadingEnabled = false;
After this I got error
A specified Include path is not valid
Please help where I am wrong.
Thanks in advance.

Many to many relationship in MVC - write to a table with foreign keys

In model I have 3 tables in relation to many many.
public class Order
{
[Key]
public int IdOrder { get; set; }
public string UserId { get; set; }
public virtual User User { get; set; }
public int IdOrderAttachment { get; set; }
public virtual OrderAttachment OrderAttachment { get; set; }
public virtual ICollection<Employee> Employee { get; set; }
[Required(ErrorMessage = "Specify the date of order acceptance")]
[Display(Name = "Date of acceptance of the order")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTimeDateOfAcceptance { get; set; }
[Display(Name = "Date of completion planning")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? DateOfCompletionPlanning { get; set; }
[Display(Name = "End Date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? EndDate { get; set; }
[Required(ErrorMessage = "Enter the subject")]
[MaxLength(200, ErrorMessage = "Name max 200 characters")]
[Display(Name = "Subject")]
public string Subject { get; set; }
public virtual ICollection<OrderPosition> OrderPosition{ get; set; }
}
public class OrderPosition
{
[Key]
public int IdOrderPosition { get; set; }
public int IdOrder { get; set; }
public int IdPosition { get; set; }
public virtual Order Order { get; set; }
public virtual Position Position { get; set; }
}
public class Position
{
[Key]
public int IdPosition { get; set; }
[Column(TypeName = "nvarchar(MAX)")]
[Display(Name = "Description")]
[UIHint("tinymce_jquery_full"), AllowHtml]
public string Description { get; set; }
public virtual ICollection<OrderPosition> OrderPosition { get; set; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateOrder(HttpPostedFileBase file, DataOrderUserViewModel viewModel)
{
var userId = User.Identity.GetUserId();
if (ModelState.IsValid)
{
if (file != null && file.ContentLength > 0)
{
string path = "/Content/Layout/CompanyFile";
if (!Directory.Exists(HttpContext.Server.MapPath(path)))
{
Directory.CreateDirectory(HttpContext.Server.MapPath(path));
}
string filename = Path.GetFileName(file.FileName);
file.SaveAs(Path.Combine(HttpContext.Server.MapPath(path), filename));
viewModel.NameFile = path+ "/" + filename;
//var nameFile = Path.GetFileName(file.FileName);
//var path = Path.Combine(Server.MapPath("/Content/Layout/CompanyFile"), nameFile);
//file.SaveAs(path);
}
var order = new Order()
{
DateTimeDateOfAcceptance = viewModel.DateTimeDateOfAcceptance,
Subject= viewModel.Subject,
UserId = userId
};
var position = new Position ()
{
Description = viewModel.Description
};
var orderAttachment = new OrderAttachment ()
{
NameFile= viewModel.NameFile,
Description = viewModel.Description2
};
db.Order.Add(order);
db.Position.Add(position);
db.OrderAttachment.Add(orderAttachment);
db.SaveChanges();
}
return RedirectToAction("Index", "Administration");
}
My question is how to write data to the OrderPosition table.
I understand that I should first write data in the Order and Position table.
Then, having two keys from these arrays, I should read them and send them to the OrderPosition as external keys where they will be saved.
What should a record of these instructions look like?
Do I need to define the following relationships in my case?
modelBuilder.Entity<OrderPosition>()
.HasKey(c => new { c.IdOrder , c.IdPosition });
modelBuilder.Entity<Order>()
.HasMany(c => c.Subject )
.WithRequired()
.HasForeignKey(c => c.IdOrder );
modelBuilder.Entity<Position>()
.HasMany(c => c.Description )
.WithRequired()
.HasForeignKey(c => c.IdPosition );

Validation failed for one or more entities.

When I try to Update IsApproved=true to approve the property, I am getting the following error.
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. The validation errors are: Please upload the image.; Please select some property features.
Please help me out. Thanx in advance.
My Model is as follows:
[Table("AddProperty")]
public class AddProperty
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[HiddenInput(DisplayValue = false)]
public int Id { get; set; }
public List<TransactionType> TransactionType_List { get; set; }//Used to populate dropdown list values
[Required(ErrorMessage = "Please select the category.")]
[Display(Name = "Category:")]
public int TransactionTypeId { get; set; }//Used to post back selected value
public virtual TransactionType TransactionType { get; set; }
public List<PropertyType> PropertyType_List { get; set; }//Used to populate dropdown list values
[Required(ErrorMessage = "Please select the property.")]
[Range(1, int.MaxValue, ErrorMessage = "Please select the property.")]
[Display(Name = "Property:")]
public int PropertyTypeId { get; set; }//Used to post back selected value
public virtual PropertyType PropertyType { get; set; }
public List<PropertyList> PropertyList_List { get; set; }//Used to populate dropdown list values
[Required(ErrorMessage = "Please select the property type.")]
[Range(1, int.MaxValue, ErrorMessage = "Please select the property type.")]
[Display(Name = "Property Type:")]
public int PropertyListId { get; set; }//Used to post back selected value
public virtual PropertyList PropertyList { get; set; }
[Required(ErrorMessage = "Property Name is required.")]
[StringLength(50, MinimumLength = 3, ErrorMessage = "Building Name length should be between 3 and 50.")]
[Display(Name = "Property Name:")]
public string PropertyName { get; set; }
public List<FlatDescription> FlatDescription_List { get; set; }//Used to populate dropdown list values
[Required(ErrorMessage = "Description is required.")]
[Display(Name = "Description:")]
public int FlatDescriptionId { get; set; }
public virtual FlatDescription FlatDescription { get; set; }
public List<Bathroom> Bathrooms_List { get; set; }//Used to populate dropdown list values
[Required(ErrorMessage = "No of Bathrooms is required.")]
[Display(Name = "No of Bathrooms:")]
public int BathroomId { get; set; }//Used to post back selected value
public virtual Bathroom Bathroom { get; set; }
public List<City> City_List { get; set; }//Used to populate dropdown list values
[Required(ErrorMessage = "Please select the city.")]
[Display(Name = "City:")]
public int CityId { get; set; }//Used to post back selected value
public virtual City City { get; set; }
[Required(ErrorMessage = "Location is required.")]
[StringLength(30, MinimumLength = 3, ErrorMessage = "Location length should be between 3 and 30.")]
[Display(Name = "Location:")]
public string Location { get; set; }
[Required(ErrorMessage = "Property Price is required.")]
[Range(typeof(decimal),"1","10000000",ErrorMessage = "Please enter valid property price.")]
[RegularExpression(#"^\d+.\d{0,2}$", ErrorMessage = "Only 2 decimal point values are allowed.")]
[Display(Name = "Enter Property Price:")]
public decimal PropertyPrice { get; set; }
//[Required(ErrorMessage = "Please upload the image.")]
[Display(Name = "Upload Image:")]
[NotMapped]
[ValidatePhoto]
public HttpPostedFileBase PropertyPhoto { get; set; }
public string ImageURL { get; set; }
public List<Facilities> Facilities_List { get; set; }//Used to populate dropdown list values
[Required(ErrorMessage = "Please select some property features.")]
[Display(Name = "Select Property Features:")]
[NotMapped]
public int[] SelectedIds { get; set; }//Used to post back selected value
public string PropertyFeatures { get; set; }
[HiddenInput(DisplayValue = false)]
public DateTime CreateDate { get; set; }
[HiddenInput(DisplayValue = false)]
public DateTime? UpdateDate { get; set; }
[HiddenInput(DisplayValue = false)]
public int CreateUser { get; set; }
[HiddenInput(DisplayValue=false)]
public int? UpdateUser { get; set; }
[HiddenInput(DisplayValue = false)]
public bool IsApproved { get; set; }
[HiddenInput(DisplayValue = false)]
public bool IsActive { get; set; }
}
Use this to track the error:
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}

AutoMapper and required fields

I am trying to create a new record using only some of the fields in my Domain Model. I have created a ViewModel for this and am using AutoMapper.
My code is failing at the minute due to the required fields that I have on my Domain Model. I have added opt=>opt.Ignore() on the necessary field however, I am still having problems.
When I remove [Required] from the StaffPresent field the record is added to the DB.
In my Global.asax.cs
Mapper.CreateMap<CustomerSupportRecord, CustomerSupportRecordForCreation>();
Mapper.CreateMap<CustomerSupportRecordForCreation, CustomerSupportRecord>().ForMember(p=>p.StaffPresent, opt=>opt.Ignore());
Domain Model
public class CustomerSupportRecord
{
public int CustomerSupportRecordID { get; set; }
[Required]
public int CustomerID { get; set; }
[Required]
public string EmployeeID { get; set; }
[Required(ErrorMessage = "Please enter a Date")]
[DataType(DataType.Date)]
[Display(Name = "Date")]
public DateTime Date { get; set; }
[Required(ErrorMessage = "Please select an Arrival Time")]
[DataType(DataType.Time)]
[Display(Name = "Arrival")]
public DateTime ArrivalTime { get; set; }
[DataType(DataType.Time)]
[Display(Name = "Departure")]
public DateTime? DepartureTime { get; set; }
[Required(ErrorMessage = "Please select a Type")]
[Display(Name = "Type")]
public int CustomerSupportTypeID { get; set; }
[Required(ErrorMessage = "Please enter the staff who were present at the Feedback")]
[Display(Name = "Staff Present at Feedback")]
public string StaffPresent { get; set; }
[Display(Name = "Setting")]
public string ReflectionSetting { get; set; }
[Display(Name = "Advisor")]
public string ReflectionAdvisor { get; set; }
[Display(Name = "Notes")]
public string Notes { get; set; }
[Display(Name = "Comments")]
public string Comments { get; set; }
// Navigation Properties
public virtual Customer Customer { get; set; }
public virtual CustomerSupportType CustomerSupportType { get; set; }
public virtual Employee Employee { get; set; }
}
ViewModel
public class CustomerSupportRecordForCreation
{
public int CustomerSupportRecordID { get; set; }
public int CustomerID { get; set; }
public string EmployeeID { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Date")]
public DateTime Date { get; set; }
[DataType(DataType.Time)]
[Display(Name = "Arrival")]
public DateTime ArrivalTime { get; set; }
[Display(Name = "Type")]
public int CustomerSupportTypeID { get; set; }
[Display(Name = "Notes")]
public string Notes { get; set; }
}
And finally my Controller
//
// GET: /CustomerSupport/CustomerSupportRecord/Create
public ActionResult Create()
{
ViewBag.CustomerSupportTypeID = new SelectList(db.CustomerSupportType, "CustomerSupportTypeID", "CustomerSupportTypeName");
var model = new CustomerSupportRecordForCreation { CustomerID = 1, EmployeeID = "20213" };
return View("Create", model);
}
//
// POST: /CustomerSupport/CustomerSupportRecord/Create
[HttpPost]
public ActionResult Create(CustomerSupportRecordForCreation customersupportrecord)
{
if (ModelState.IsValid)
{
var newRecord = Mapper.Map<CustomerSupportRecordForCreation, CustomerSupportRecord>(customersupportrecord);
db.CustomerSupportRecord.Add(newRecord);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CustomerSupportTypeID = new SelectList(db.CustomerSupportType, "CustomerSupportTypeID", "CustomerSupportTypeName", customersupportrecord.CustomerSupportTypeID);
return View(customersupportrecord);
}
AutoMapper's configuration doesn't have anything to do with validation attributes, it just specifies the rules for how to map objects between each-other.
In your case, the mapping:
Mapper.CreateMap<CustomerSupportRecordForCreation, CustomerSupportRecord>().ForMember(p=>p.StaffPresent, opt=>opt.Ignore());
tells AutoMapper not to copy the StaffPresent property.
If your database model has a [Required] attribute, you'll still need to set that data elsewhere.
One thing to note based on your comment, it's a good idea to add validation to your ViewModels, as it prevents you from calling your database methods with improper data, gives you client side validation, and lets you enforce different constraints than your model might require.

Resources