Loading data from three related tables in ASP.NET Core using Entity Framwork Core in one-to-many relationship makes some data not displayed - linq

I have three tables Customer, Loan and LoanHistories. Customer table is related to Loan table in a one-to-many relationship, and the Loan table is related to LoanHistories in one-to-many relationship as well.
The following are the C# classes for these tables:
public class Customer
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "ID NO")]
public int CustomerID { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Phone Number")]
public string PhoneNo { get; set; }
[Display(Name = "Nearest Primary School")]
public string NearestPrimarySchool { get; set; }
[Display(Name = "Photo")]
public string Photo { get; set; }
public ICollection<Loan> loans { get; set; }
// public IEnumerable<LoansHistories> loansHistories { get; set; }
// public ICollection<WorkForLiving> workForLivings { get; set; }
// public ICollection<CustomersCharacterBehavior> customersCharacterBehaviors { get; set; }
}
public class Loan
{
[Key]
public int LoanID { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal LoanAmount { get; set; }
[NotMapped]
public decimal TotalRepaidIn { get; set; }
[NotMapped]
public decimal Balance { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
[Display(Name = "Loan Balance")]
private decimal _LoanBalance;
public decimal LoanBalance
{
get { return LoanAmount * interestRate; }
set { _LoanBalance = value; }
}
[Display(Name = "Interest Rate")]
public decimal interestRate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Application Date")]
public DateTime ApplicationDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Disbursement Date")]
public DateTime DisbursmentDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Due Date")]
public DateTime DueDate { get; set; }
[Display(Name = "Defaulted")]
public bool Defaulted { get; set; }
[Display(Name = "Approved")]
public bool Approved { get; set; }
//Navigation property
public int CustomerID { get; set; }
public Customer customer { get; set; }
//public ICollection<LoanComments> loancomments { get; set; }
public ICollection<LoansHistories> loansHistories { get; set; }
}
public class LoansHistories
{
[Key]
public int HistID { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
[Display(Name = "Repaid Amount")]
public decimal RePaidIn { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Repayement Date")]
public DateTime RepayementDateDate { get; set; }
[Display(Name = "No of paying interest only")]
public int NoOfPayinyingIntrestOnly { get; set; }
// Navigation properties
public int LoanID { get; set; }
public Loan loan { get; set; }
// Navigation property
// public int CustomerID { get; set; }
// public Customer customer { get; set; }
}
This is the LoansController that loads data from Loans and LoansHistories tables:
[HttpGet]
public async Task<ActionResult<IEnumerable<Loan>>> Getloans()
{
var data = await _context.loans
.Include(lh => lh.loansHistories)
.Select(l => new Loan()
{
TotalRepaidIn = l.loansHistories.Select(lh => lh.RePaidIn).Sum(),
Balance = l.loansHistories.Select(lh => lh.RePaidIn).Sum()-l.LoanAmount,
loansHistories = l.loansHistories,
ApplicationDate = l.ApplicationDate,
Defaulted = l.Defaulted,
DisbursmentDate = l.DisbursmentDate,
DueDate = l.DueDate,
LoanID = l.LoanID,
Approved = l.Approved,
interestRate = l.interestRate,
LoanAmount = l.LoanAmount
}).ToListAsync();
return data;
}
This is the data in JSON format:
[
{
"loanID":1,
"loanAmount":1000.0000,
"totalRepaidIn":202700.0000,
"balance":201700.0000,
"loanBalance":15000.000000,
"interestRate":15.00,
"applicationDate":"2022-03-28T00:00:00",
"disbursmentDate":"2022-03-28T00:00:00",
"dueDate":"2022-04-28T00:00:00",
"defaulted":false,
"approved":true,
"customerID":0,
"customer":null,
"loansHistories":[
{
"histID":1,
"rePaidIn":500.0000,
"repayementDateDate":"2022-03-28T00:00:00",
"noOfPayinyingIntrestOnly":1,
"loanID":1,
"loan":null
}
]
}
]
I want to load data from customer controller but I found entity TotalRepaidIn to be Zero, How can I make it return a value has its returning in loan controller? without having entity totalRepaidIn":0.0
Customer controller:
// GET: api/CustomersApi
[HttpGet]
public async Task<ActionResult<IEnumerable<Customer>>> Getcustomers()
{
return await _context.customers.Include(l=>l.loans).ThenInclude(h=>h.loansHistories).ToListAsync();
}
It returns the following Json data:
[
{
"customerID":30290122,
"firstName":"Isaac",
"lastName":"Kiplagat",
"phoneNo":"0724797768",
"nearestPrimarySchool":"Mokwo",
"photo":"photo",
"loans":[
{
"loanID":1,
"loanAmount":1000.0000,
"totalRepaidIn":0.0,
"balance":0.0,
"loanBalance":15000.000000,
"interestRate":15.00,
"applicationDate":"2022-03-28T00:00:00",
"disbursmentDate":"2022-03-28T00:00:00",
"dueDate":"2022-04-28T00:00:00",
"defaulted":false,
"approved":true,
"customerID":30290122,
"loansHistories":[
{
"histID":1,
"rePaidIn":500.0000,
"repayementDateDate":"2022-03-28T00:00:00",
"noOfPayinyingIntrestOnly":1,
"loanID":1
}
]
}
]
}
]

One way is like the previous did you can select the new Customer instance and set value for it one by one.
Another easier way, you can change your property to below to calculate the RePaidIn:
using System.Linq; //import this namespace...
public class Loan
{
[Key]
public int LoanID { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal LoanAmount { get; set; }
private decimal _TotalRepaidIn;
[NotMapped]
public decimal TotalRepaidIn
{
get { return loansHistories.Sum(sum => sum.RePaidIn); }
set { _TotalRepaidIn = value; }
}
//other properties
public ICollection<LoansHistories> loansHistories { get; set; } = new List<LoansHistories>();
}
And in your LoansController, you can improve the action to below:
var data = await _context.loans.Include(lh => lh.loansHistories).ToListAsync();
Customer Controller can also get the correct value for TotalRepaidIn.

Related

Invalid Column Name Entity guessing a foreign key that isn't there

I don't really understand what's happening here. From my research I gather that entity is trying to guess the name of a foreign key and it's not there, so it's throwing an "Invalid Column Name" error. The problem is that the model/table in question does not have any foreign keys. So I'm really confused.
Here's the code that throws the error:
foreach (TechnologyProjectPlanModel result in results)
{
//get approvers for plan
int id = result.Id;
try
{
List<ApprovalModel> approvers = db.ApprovalModels.Where(m => m.FormId == result.Id).Select(m => m).ToList(); //ERROR HERE
if (approvers != null)
{
result.Approvers = approvers.ToList();
}
}
catch (Exception e)
{
}
}
Here's the ApprovalModel:
public class ApprovalModel
{
[Key]
public int Id { get; set; }
public int ApprovalProcessId { get; set; }
public int FormId { get; set; }
public int UserId { get; set; }
public bool? Approved { get; set; }
}
And here's the TechnologyProjectPlanModel referenced in the foreach loop:
public class TechnologyProjectPlanModel
{
[Key]
public int Id { get; set; }
public int FormId { get; set; }
public int UserId { get; set; }
public string FormType { get; set; }
public int Status { get; set; }
public int Hidden { get; set; }
public DateTime DateSubmitted { get; set; }
public DateTime DateFinalized { get; set; }
public List<QuoteUploadsModel> Quotes { get; set; }
public List<ApprovalModel> Approvers { get; set; }
[Required]
[Display(Name = "Please Select Your School")]
public string School { get; set; }
[Required]
[Display(Name = "Requestor")]
public string Requestor { get; set; }
[Display(Name = "Title")]
public string Title { get; set; }
[Required]
[DataType(DataType.PhoneNumber)]
[Display(Name = "Phone Number")]
[Phone]
public string PhoneNumber { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email Address")]
[EmailAddress]
public string Email { get; set; }
[Required]
[Display(Name = "Project Title")]
public string ProjectTitle { get; set; }
[Display(Name = "Requested Completion Date")]
public DateTime RequestedCompletionDate { get; set; }
[Required]
[Display(Name = "Project Description")]
public string ProjectDescription { get; set; }
[Display(Name = "Teacher/Room Number")]
public string TeacherGroup { get; set; }
[Display(Name = "1")]
public bool Grade1 { get; set; }
[Display(Name = "2")]
public bool Grade2 { get; set; }
[Display(Name = "3")]
public bool Grade3 { get; set; }
[Display(Name = "4")]
public bool Grade4 { get; set; }
[Display(Name = "5")]
public bool Grade5 { get; set; }
[Display(Name = "6")]
public bool Grade6 { get; set; }
[Display(Name = "7")]
public bool Grade7 { get; set; }
[Display(Name = "8")]
public bool Grade8 { get; set; }
[Display(Name = "9")]
public bool Grade9 { get; set; }
[Display(Name = "10")]
public bool Grade10 { get; set; }
[Display(Name = "11")]
public bool Grade11 { get; set; }
[Display(Name = "12")]
public bool Grade12 { get; set; }
[Display(Name = "Kindergarten")]
public bool Kindergarten { get; set; }
[Display(Name = "Describe how this plan will be continued if events cause programs or equipment to no longer be available. For example, if equipment purchased needs repair what funding source will be used for repair or replacement? For programs that have annual subscription fees, what funds will be used to continue the program from year to year?")]
public string Sustainability { get; set; }
public bool MultipleFundingSource { get; set; }
[Required(ErrorMessage="*")]
[Display(Name = "Funding Source")]
public string FundingSource1 { get; set; }
[Required(ErrorMessage = "*")]
public string FundingSource2 { get; set; }
[Required(ErrorMessage = "*")]
public string FundingSource3 { get; set; }
[Required(ErrorMessage = "*")]
public string FundingSource4 { get; set; }
[Required(ErrorMessage = "*")]
public string FundingSource5 { get; set; }
[Required]
[Display(Name = "Total Estimated Project Costs:")]
public float TotalEstimatedProjectCosts { get; set; }
//----------------------Additional Information
[Display(Name = "Additional Comments:")]
public string AdditionalComments { get; set; }
[Display(Name = "Additional Supporting Documents:")]
public string AdditionalSupportingDocuments { get; set; }
}
The exact error is:
An error occurred while executing the command definition. See the inner exception for details.
Inner Exception:
Invalid column name 'TechnologyProjectPlanModel_Id'.
That column name isn't referenced anywhere in my code, so it must be inferring it from something.
Any ideas? Thanks!
Entity Framework relies on conventions to determine what it thinks your DB looks like. In this case, it thinks the ApprovalModel table should have a foreign key to the TechnologyProjectPlanModel table. Trimming down your entities to the relevant fields, it becomes apparent why it thinks this:
public class ApprovalModel
{
}
public class TechnologyProjectPlanModel
{
public List<ApprovalModel> Approvers { get; set; }
}
In database terms, the relationship that would most likely exist in order for there to be multiple ApprovalModel's per TechnologyProjectPlanModel would be for ApprovalModel's to have a foreign key to TechnologyProjectPlanModel's.
How does TechnologyProjectPlanModel.Approvers get set? If it doesn't have anything to do with Entity Framework and you don't want it to try populating this property via it's conventions, you can explicitly tell it not to make that assumption by telling it the property is not mapped like so:
[NotMapped]
public List<ApprovalModel> Approvers { get; set; }
If you do have this relationship, you need to give EF some more context so it doesn't make best guess assumptions. For example, if the foreign key does exist, place it in ApprovalModel along with the relevant navigation property that can further tell EF what your DB looks like:
public class ApprovalModel
{
public int TechnologyProjectPlanModelId { get; set; }
// ForeignKey attribute usually not necessary unless you need to tell EF
// about a property that doesn't follow the usual "{OtherEntityName}Id"
// naming convention.
[ForeignKey("TechnologyProjectPlanModelId")]
public TechnologyProjectPlanModel TechnologyProjectPlanModel { get; set; }
}
public class TechnologyProjectPlanModel
{
public List<ApprovalModel> Approvers { get; set; }
}
You know if you do the mapping correctly, that block of code is unnecessary because EF will retrieve results.Approvers for you.
You can use the Attribute based mapping directly on your model or you can use the Code First Configuration to map your foreign key properly.
Once you've properly mapped the foreign key, the block of code you pasted is unnecessary, EF does the load for you.

Multiple relationships to UserId in one table

I have a UserProfile with a UserId. I need to create a relationship to a table Scorecards where there are multiple columns that need to have a relationship with UserId. They are ScorerId, CreatedById, AgentId, ModifiedById, PublishedById ....
I am unsure of how this would be done via code first approach with mvc 4 and entity 5?
Any Help would be appreciated.
public class ScorecardsModel
{
[Key]
public int ScorecardId { get; set; }
[Required]
[Display(Name = "Agent ID")]
public int AgentId { get; set; }
[Required]
[Display(Name = "Agent Name")]
public string AgentName { get; set; }
[Display(Name = "Department")]
public int DepartmentId { get; set; }
[Required]
public DateTime? CreatedOn { get; set; }
[Required]
[Display(Name = "Scorer")]
public int CreatedById { get; set; }
[Required]
[Display(Name = "Call")]
public int CallNum { get; set; }
[Required]
[Display(Name = "Call Date/Time")]
public DateTime? CallDateTime { get; set; }
[Required]
[Display(Name = "Procedural Score")]
[Range(0, 100)]
public int ProceduralScore { get; set; }
[Required]
[Display(Name = "Soft Skills Score")]
[Range(0, 100)]
public int SoftSkillsScore { get; set; }
[Required]
[Display(Name = "Total Score")]
[Range(0, 100)]
public int TotalScore { get; set; }
[Required]
public bool Modified { get; set; }
[Required]
[Display(Name = "Modified By")]
public int ModifiedById { get; set; }
[Required]
[Display(Name = "Modified On")]
public DateTime? ModifiedOn { get; set; }
public bool Completed { get; set; }
[Required]
[Display(Name = "Completed By")]
public int CompletedById { get; set; }
[Required]
[Display(Name = "Completed On")]
public DateTime? CompletedOn { get; set; }
public bool Published { get; set; }
[Required]
[Display(Name = "Published By")]
public int PublishedById { get; set; }
[Required]
[Display(Name = "Published On")]
public DateTime? PublishedOn { get; set; }
[Required]
[Display(Name = "Template")]
public int TemplateId { get; set; }
And UserProfile:
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string DisplayName { get; set; }
Thanks in advance.
Look at the following link Relationships in EF5 - Code First. It might be what you are looking for.
You can also refer to this if you get stuck.
And lastly in this ASP Forum, is some more information

EF 5.0 Code First navigation property null for only one property

I seem to be having a problem with the following model using EF 5.0 CodeFirst:
When I try and do a listing with SalesPlanActivity I am unable to get the Activity name from the navigational property
i.e. If my model is SalesPlanActivity, model.Activity <--- is null, yet model.Company and model.SalesPlan are fine.
The idea is that a company has a library of activities, each company has a number of salesplans, each salesplans has a number of activities (which come from the activity library)
Am I mapping this incorrectly?
Should the mapping between SalesPlanActivity and Activity be 1:1?
I've added the following relationships
// Relationships
modelBuilder.Entity<SalesPlanActivity>().HasRequired(t => t.Activity)
.WithMany(t => t.SalesPlanActivities)
.HasForeignKey(d => new { d.CompanyId, d.ActivityId });
modelBuilder.Entity<SalesPlanActivity>().HasRequired(t => t.SalesPlan)
.WithMany(t => t.SalesPlanActivities)
.HasForeignKey(d => new { d.SalesPlanId, d.CompanyId });
public class Activity : IAuditable
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ActivityId { get; set; }
[Key, Column(Order = 1)]
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
[Display(Name = "Activity Name"), Required, StringLength(256)]
public string Name { get; set; }
public virtual ICollection<SalesPlanActivity> SalesPlanActivities { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedOn { get; set; }
public Guid CreatedBy { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedOn { get; set; }
public Guid ModifiedBy { get; set; }
}
public class Company : IAuditable
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CompanyId { get; set; }
[Display(Name = "Company Name"), Required, StringLength(256)]
public string Name { get; set; }
public virtual ICollection<Activity> Activities { get; set; }
public virtual ICollection<SalesPlan> SalesPlans { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedOn { get; set; }
public Guid CreatedBy { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedOn { get; set; }
public Guid ModifiedBy { get; set; }
}
public class SalesPlan : IAuditable
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int SalesPlanId { get; set; }
[Key, Column(Order = 1)]
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
[Display(Name = "Sales Plan Name"), Required, StringLength(256)]
public string Name { get; set; }
[Display(Name = "Total Points"), Required]
public decimal TotalPoints { get; set; }
public virtual ICollection<SalesPlanActivity> SalesPlanActivities { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedOn { get; set; }
public Guid CreatedBy { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedOn { get; set; }
public Guid ModifiedBy { get; set; }
}
public class SalesPlanActivity : IAuditable
{
[Key, Column(Order = 0)]
public int SalesPlanId { get; set; }
public virtual SalesPlan SalesPlan { get; set; }
[Key, Column(Order = 1)]
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
[Key, Column(Order = 2)]
public int ActivityId { get; set; }
public virtual Activity Activity { get; set; }
public decimal Points { get; set; }
public int SortOrder { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedOn { get; set; }
public Guid CreatedBy { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedOn { get; set; }
public Guid ModifiedBy { get; set; }
}

Complex Linq to Entities Query

I have done simple LINQ queries but I am stumped on the 2 I need to create now. Basically I am going to get a class ID sent in. I will post the classes the entities are based on below.
public class ScheduledClass
{
public ScheduledClass()
{
Attendees = new List<ClassAttendee>();
}
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[HiddenInput(DisplayValue = false)]
[Required(ErrorMessage = "Please enter a topic")]
public int ClassTopicID { get; set; }
[Display(Name = "Topic")]
public virtual ClassTopic ClassTopic { get; set; }
[HiddenInput(DisplayValue = false)]
public int ClassTypeID { get; set; }
[Display(Name = "Class Type")]
public virtual ClassType ClassType { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name = "Class Date")]
public DateTime ClassDate { get; set; }
[Display(Name = "Attendees")]
public virtual ICollection<ClassAttendee> Attendees { get; set; }
}
public ClassTopic()
{
Products = new List<ClassTopicProduct>();
}
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[Required(ErrorMessage = "Please enter a title")]
public string Title { get; set; }
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[Display(Name = "Products")]
public virtual ICollection<ClassTopicProduct> Products { get; set; }
}
public class ClassTopicProduct
{
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[HiddenInput(DisplayValue = false)]
public int ClassTopicID { get; set; }
[ForeignKey("ClassTopicID")]
public ClassTopic ClassTopic { get; set; }
[HiddenInput(DisplayValue = false)]
public int ProductID { get; set; }
[ForeignKey("ProductID")]
public ProductType ProductType { get; set; }
}
public class CustomerEmail
{
public CustomerEmail()
{
CustomerEmailModules = new List<CustomerEmailModule>();
}
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[HiddenInput(DisplayValue = false)]
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
public string Name { get; set; }
public string Email { get; set; }
[DataType(DataType.PhoneNumber)]
public string PhoneNumber { get; set; }
[Display(Name = "Product Update")]
public Boolean SendProductUpdateEmail { get; set; }
[Display(Name = "Expiration ")]
public Boolean SendExpirationEmail { get; set; }
[Display(Name = "Products")]
public virtual ICollection<CustomerEmailModule> CustomerEmailModules { get; set; }
}
public class CustomerEmailModule
{
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[HiddenInput(DisplayValue = false)]
public int CustomerEmailID { get; set; }
public CustomerEmail CustomerEmail { get; set; }
[HiddenInput(DisplayValue = false)]
public int? ProductID { get; set; }
[ForeignKey("ProductID")]
public ProductType ProductType { get; set; }
}
EDIT___________________________
public class ProductType
{
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[Required(ErrorMessage = "Please enter a product type description")]
public string Description { get; set; }
public virtual ICollection<ProductTypeDetail> ProductDetails { get; set; }
}
EDIT_________________________________
So I am basically trying to send emails to people who might be interested in an upcoming class. Each class has a class topic. The class topic has 1 or more products associated with them. When I get the Class ID I need to go get all of the products associated with the class topic for the class. Once I have that I need to go look at CustomerEmails. Each CustomerEmail has any number of products that they are interested in associated with them. I need to find any CustomerEmail that has CustomerEmailModules where the PRoductID = Any of the product IDs in the Class Topic Products results. Here is what I tried to do below that is not working.
public JsonResult GetEmailClassInterest(int id)
{
var classprods = UoW.ScheduledClasses
.Where(o => o.ID == id)
.Select(p => new
{
p.ClassTopic.Products
});
var customeremails = from p in UoW.CustomerEmails where classprods.Any(z => z.Products.Any(x => x.ID == p.ID)) select p.Email;
return Json(customeremails, JsonRequestBehavior.AllowGet);
}
The query seems to run through ok but I get no results and there shoudl be base don the data I have. If anyone can tell me what I am doing wrong I would appreciate it.
Thanks
Try doing this:
var classprods = UoW.ScheduledClasses
.Where(o => o.ID == id)
.SelectMany(sched => sched.ClassTopic.Products.Select(prod => prod.ProductID));
var customerEmails = UoW.CustomerEmailModules.Include("CustomerEmails")
.Where(mod => mod.ProductID != null && classprods.Contains(mod.ProductID)
.Select(mod => mod.CustomerEmail.Email);

MVC 3 Dropdowns & Multiple Model ViewModel

I'm pretty new to MVC, but I'm trying to set up a two step user registration system. I have an register model and several other models in a viewmodel called Registration. A user will have a profile based on the register model and then they will select a Producer/Distributor/Restaurant/Importer that they are part of, or create a new one of those. My ViewModel that is returned doesn't validate or pickup the values in my dropdownlists. They populate correctly, but on the post they aren't in the vm. Below is my view/controller/and models. I've been searching the net for 2 days with no luck. Also, if you think my method of registration is wacky, let me know. Thanks!
controller:
public class RegistrationController : Controller
{
private vfContext db = new vfContext();
//
// GET: /Registration/
public ActionResult Register()
{
ViewBag.UserTypeID = new SelectList(db.UserTypes, "UserTypeID", "Name");
ViewBag.ProducerID = new SelectList(db.Producers, "ProducerID", "Name");
ViewBag.PublicationID = new SelectList(db.Publications, "PublicationID", "Name");
ViewBag.ImporterID = new SelectList(db.Importers, "ImporterID", "Name");
ViewBag.DistributorID = new SelectList(db.Distributors, "DistributorID", "Name");
ViewBag.RestaurantID = new SelectList(db.Restaurants, "RestaurantID", "Name");
RegistrationViewModel reg = new RegistrationViewModel();
ViewData.Model = reg;
return View("Registration");
}
[HttpPost]
public ActionResult Register(RegistrationViewModel vm)
{
if (ModelState.IsValid)
{
MembershipCreateStatus createStatus;
//email is userid
Membership.CreateUser(vm.Register.Email, vm.Register.Password, vm.Register.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
Profile current = Profile.GetProfile(vm.Register.Email);
current.FirstName = vm.Register.FirstName;
current.LastName = vm.Register.LastName;
current.Address1 = vm.Register.Address1;
current.Address2 = vm.Register.Address2;
current.City = vm.Register.City;
current.State = vm.Register.State;
current.Postal = vm.Register.Postal;
current.UserTypeID = vm.Register.UserTypeID;
view - i'm having a hard time copying it over, so the issue is with ddls, so here is how I have the user type id one done
#model vf2.Models.RegistrationViewModel
<div class="editor-label">
#Html.LabelFor(model => model.Register.UserTypeID, "User Type")
</div>
<div class="editor-field">
#Html.DropDownList("UserTypeID", String.Empty)
#Html.ValidationMessageFor(m => m.Register.UserTypeID)
</div>
Models:
public class RegistrationViewModel
{
public RegisterModel Register { get; set; }
public Producer Producer { get; set; }
public Distributor Distributor { get; set; }
//public Publication Publication { get; set; }
public Restaurant Restaurant { get; set; }
public Importer Importer { get; set; }
}
Here is my register model.
public class RegisterModel
{
//[Required]
//[Display(Name = "User name")]
//public string UserName { get; set; }
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Address")]
public string Address1 { get; set; }
[Display(Name = "Address Cont.")]
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postal { get; set; }
public string Country { get; set; }
[DataType(DataType.PhoneNumber)]
public string Phone { get; set; }
public int ProducerID { get; set; }
public int DistributorID { get; set; }
public int PublicationID { get; set; }
public int ImporterID { get; set; }
public int RestaurantID { get; set; }
public virtual Producer Producer{ get; set; }
public virtual Distributor Distributor { get; set; }
public virtual Publication Publication { get; set; }
public virtual Importer Importer { get; set; }
public virtual Restaurant Restaurant { get; set; }
[Required]
public int UserTypeID { get; set; }
public virtual UserType UserType { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
producer model:
public class Producer
{
public int ProducerID { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postal { get; set; }
public string Country { get; set; }
[DataType(DataType.PhoneNumber)]
public string Phone { get; set; }
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
public string Website { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public string UpdatedBy { get; set; }
public DateTime? UpdatedOn { get; set; }
public Boolean Active { get; set; }
public virtual ICollection<Wine> Wines { get; set; }
}
I think I figured this out by adding a the following to my viewmodel:
public IEnumerable<UserType> UserTypes { get; set; }
public IEnumerable<Producer> Producers { get; set; }
and then this to my view:
#Html.DropDownListFor(m=>m.Register.UserTypeID,new SelectList(Model.UserTypes,"UserTypeID","Name"),"Select account type")

Resources