EF Code First and ASP.NET membership provider - asp.net-mvc-3

I am building a web application using MVC 3. It has users with different roles and privileges. I am using EF Code First approach for database creation. My model class for user is:
public class Users
{
public int UserID { get; set; }
public Name Name { get; set; }
public Address Address { get; set; }
public Contact Contact { get; set; }
}
public class Name
{
[Required, MaxLength(50), Display(Name = "First Name"), Column("FirstName")]
public string FirstName { get; set; }
[MaxLength(50), Display(Name = "Middle Name"), Column("MiddleName")]
public string MiddleName { get; set; }
[Required, MaxLength(50), Display(Name = "Last Name"), Column("LastName")]
public string LastName { get; set; }
}
public class Address
{
[Required, MaxLength(50), Display(Name = "Street"), Column("Street")]
public string Street { get; set; }
[Required, MaxLength(50), Display(Name = "City"), Column("City")]
public string City { get; set; }
[Required, MaxLength(50), Display(Name = "Country"), Column("Country")]
public string Country { get; set; }
[Required, MaxLength(5), Display(Name = "Postal Code"), Column("PostalCode")]
public string PostalCode { get; set; }
}
public class Contact
{
[Required, MaxLength(50), Display(Name = "Email"), Column("Email")]
public string Email { get; set; }
[Required, MaxLength(50), Display(Name = "Phone"), Column("Phone")]
public string Phone { get; set; }
[Required, MaxLength(50), Display(Name = "Fax"), Column("Fax")]
public string Fax { get; set; }
}
But for roles and authentication I want to use the default aspnetdb.mdf of App_Data folder. How do I link my Users table with the default Users table of aspnetdb.mdf?

Since it seems like you are creating a new site and DB, I wouldn't go about it this way, unless you have to for whatever reason.
I would use UserProfile to store additional info like address, phone, fax, etc. for the user, take a look at the Membership User Profile API to add the custom properties.
Also this article may help, it's a bit old but it should help you if needed.

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.

How to include related table in LINQ query?

I have two classes, Company and CompanyAddress.
For every Company there can be multiple CompanyAddresses, such as Invoice address and correspondence address.
Via entity framework, I'm trying to include all CompanyAddresses that belong the Company. However, I keep getting the following debug error:
An exception of type 'System.InvalidOperationException' occurred in System.Data.Entity.dll but was not handled in user code
Additional information: A specified Include path is not valid. The EntityType 'StatelyTechAdmin.Models.Company' does not declare a navigation property with the name 'CompanyAddresses'.
Can anyone advise me on why I cannot include all addresses in my LINQ query? Please note I am very new to Entity Framework.
Company Class
public class Company
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public virtual long CompanyId { get; set; }
[Required]
[Display(Name = "Company Name")]
public virtual string Name { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual IEnumerable<CompanyAddress> CompanyAddresses { get; set; }
}
CompanyAddress Class
public class CompanyAddress
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public virtual long CompanyAddressId { get; set; }
[Required]
public virtual long CompanyId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[Required]
public virtual int CompanyAddressTypeId { get; set; }
[ForeignKey("CompanyAddressTypeId")]
public virtual CompanyAddressType CompanyAddressType { get; set; }
[Display(Name = "Address 1")]
public virtual string Address1 { get; set; }
[Display(Name = "Address 2")]
public virtual string Address2 {get; set; }
[Display(Name = "Town")]
public virtual string Town { get; set; }
[Display(Name = "City")]
public virtual string City { get; set; }
[Required]
public virtual long CountyId { get; set; }
[ForeignKey("CountyId")]
[Display(Name = "County")]
public virtual County County { get; set; }
[Required]
[Display(Name = "Postal Code")]
public virtual string PostalCode { get; set; }
public virtual DateTime CreatedDate { get; set; }
}
Calling Method from MVC Action
public ActionResult Index()
{
var comp = db.Companies.Include(a => a.CompanyAddresses).ToList();
return View(comp);
}
All advice welcome! Thank you for your time.
You can't use IEnumerable for your navigation property. You need to use ICollection or a type derived from it.
How do I load related entities of type IEnumerable<T>

asp.net MVC User Friends LazyLoad

If i try to use code first,
The User Class:
public class User
{
[Key]
public Guid ID { get; set; }
[Required(ErrorMessage = "You must pick a user name")]
[DisplayName("User Name")]
public string Username { get; set; }
[Required]
public string FullName { get; set; }
[Required(ErrorMessage = "You give a valid email address")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
public DateTime CreateAt { get; set; }
public string Image { get; set; }
public bool RemeberMe { get; set; }
public bool Dummy { get; set; }
public virtual ICollection<UserFriend> Friends { get; set; }
}
The UserFriend Class: - hold the relationship between users
public class UserFriend
{
[Key, Column(Order = 0), ForeignKey("User")]
public Guid UserId { get; set; }
public User User { get; set; }
[Key, Column(Order = 1), ForeignKey("Friend")]
public Guid FriendId { get; set; }
public User Friend { get; set; }
public DateTime DateCreated { get; set; }
}
User Repository:
public class UserRepository : IUserRepository
{
public User GetUserByName(string userName)
{
return context.Users.FirstOrDefault(u => u.Username == userName);
}
}
if i try to user this methods:
var userRepo = new UserRepository(new DataContext());
User user = userRepo.GetUserByName(User.Identity.Name);
PROBLEM: user.Friends.first().Friend return null
if i got it right my lazy load not working.
help please...
link to the project - https://github.com/RanDahan/barker
In the contructor of User class you should create new instance of Friends collection
Friends = new HashSet<UserFriend>()
Also, i think navigation properties in UserFirends should also have been declared as virtual.

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")

ASP.NET MVC3 Eager Client-Validation, FluentHTML and Nested ViewModels

I'm using FluentHTML (from MvcContrib) to layout my HTML mark-up. I want to use eager unobtrusive client-validation provided by jquery.validate library. I got everything working correctly except for properties of nested ViewModels. Example:
public class RegisterPageViewModel
{
[Required(ErrorMessage = "First Name cannot be empty.")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name cannot be empty.")]
public string LastName { get; set; }
[Required(ErrorMessage = "Email cannot be empty.")]
[RegularExpression(#"^\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "Invalid Email Format.")]
public string Email { get; set; }
[Required(ErrorMessage = "Password field cannot be empty.")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required(ErrorMessage = "You have to confirm your password.")]
[Compare("Password", ErrorMessage = "Passwords must match.")]
[DataType(DataType.Password)]
public string PasswordConfirm { get; set; }
[Required]
public AddressDto Address { get; set; }
public bool TermsOfUse { get; set; }
[Required(ErrorMessage = "Nickname is required")]
public string Nickname { get; set; }
public string MiddleName { get; set; }
[Required(ErrorMessage = "Birthdate is required")]
public string Birthdate { get; set; }
public string Phone { get; set; }
[Required(ErrorMessage = "Mobile number is required")]
public string Mobile { get; set; }
public string RakimMelieh { get; set; }
public string ReferralNickname { get; set; }
}
It works perfectly for ALL of the properties except for those inside the Address property, although I decorated the properties of the AddressDto with validation attributes as well:
public class AddressDto
{
public int Id { get; set; }
[Required(ErrorMessage = "Address Name is required.")]
public string Name { get; set; }
public string Country { get; set; }
public string District { get; set; }
public string City { get; set; }
public string Area { get; set; }
[Required(ErrorMessage = "Address Details are required.")]
public string Details { get; set; }
public bool IsDefault { get; set; }
}
The same thing happens for other view models as well where there are nested view models inside them. One thing I noticed when inspecting the input fields FireBug is that they always have the valid class on them, even when they're not really valid (according to the annotations decorating their properties).
Any thoughts how I can solve this problem?

Resources