I have a simple scenario, but can't figure out how to setup a ViewModel. I have a CustomerController.cs, Create.cshtml, and Edit.cshtml. On these views I have fields to take in basic customer information like Name, Phone, Fax, Email.
There is a foreign key in my Customer table called AddressId. The Address table consists of columns like AddressId, Address1, Address2, City, State, Zip.
I am using Entity Framework so I can simply get a customer's address by doing Customer.Address
My form consists of both the customer and address fields which is where my confusion comes in. Do I need all of the address fields, do I at least need AddressId which is the foreign key, do I not need AddressId, but simply Address, etc..
Here is what I currently have in my CustomerInfoViewModel:
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public int AddressId { get; set; }
//Address fields
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
[Display(Name = "State")]
public int StateId { get; set; }
[Display(Name = "Zip Code")]
public string ZipCode { get; set; }
[Display(Name = "Country")]
public int CountryId { get; set; }
I have a State and Country dropdown on the page so I figured I would only need the Ids of State and Country. So I am confused on whether I do all of the above or rather than add all of the Address fields simply add:
public Address Address { get; set; }
You should able to do it either. The biggest deciding factor is if you want to pull in and bind properties to the view model or the entity model. So whether you decide:
[HttpPost]
public ActionResult Edit(CustomerInfoViewModel vm)
Or
[HttpPost]
public ActionResult Edit(Customer model)
It's really more about code style.
Related
I'm doing an ASP.NET MVC project and I'm having trouble to make the create view work: it doesn't save data into two tables. I'm creating a client with name, email, address, zipcode + city.
These are my two tables:
Clients table:
public int ClientID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public Nullable<int> MailID { get; set; }
public virtual PostOffices PostOffices { get; set; }
And then I have PostOffices table:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public PostOffices()
{
this.Clients = new HashSet<Clients>();
}
public int MailID { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Clients> Clients { get; set; }
I have written a controller looking like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ClientID,Name,Email,Address,MailID")] Clients clients)
{
if (ModelState.IsValid)
{
db.Asiakkaat.Add(asiakkaat);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(asiakkaat);
}
In the view it shows everything and lets me enter data into all of the input boxes, but it only saves data to the Clients table like name, email, address, but it doesn't save anything into the PostOffices table (meaning zipcode and city).
Is there something wrong with my controller? Or should I somehow add into a client class a zipcode + city, and not the MailID? I can't get it to work.
I appreciate the help!
Just remove [Bind] and never use this attribute in the future
public ActionResult Create( Clients clients)
I'm attempting to create an Address table which will contain a Country entity.
The Address table can only contain 1 Country entry. I'd like to have another table which contains a list of countries. On the UI I want a drop down list which will list all of the countries (which reside in the Countries table). When a country is selected, the Country entity in the Address table will be populated.
I'm unsure about the relationship between the Address table and the Country table. It seems to me that the Countries table is not a dependent table (stand alone).
I'm unsure how to annotate my properties to get the desired result.
Currently this is what my Address model looks like.
public class Address
{
[Key]
[DatabaseGenerated( DatabaseGeneratedOption.Identity )]
public int AddressId { get; set; }
[Required]
[MaxLength( 255 )]
public string AddressLine1 { get; set; }
[Required]
[MaxLength( 50 )]
public string Region { get; set; }
[Required]
public Country Country { get; set; }
}
And the Country model.
public class Country
{
[Key]
[DatabaseGenerated( DatabaseGeneratedOption.Identity )]
public int CountryId { get; set; }
[Required]
public string CountryName { get; set; }
public Address Address { get; set; }
[ForeignKey( nameof( AddressId ) )]
public int AddressId { get; set; }
}
And the context
public sealed class LodgingCrmContext : DbContext
{
public LodgingCrmContext( DbContextOptions<LodgingCrmContext> options )
: base( options )
{
}
public DbSet<Country> Countries { get; set; }
public DbSet<Address> Addresses { get; set; }
}
The Address FK and the Address navigation property in the Country model makes no sense to me. You wouldn't navigate from a country to an address. Furthermore the Countries table should be a standalone table, not dependent on the Address table. How can I accomplish this?
I'm a little confused and could use some help.
I have the following model:
public sealed class Consignor : TwoNames
{
public Consignor()
{
Address = new Address();
}
}
It's mother class TwoNames looks like this:
public abstract class TwoNames : Search
{
[Required]
public int AddressId { get; set; }
public virtual Address Address { get; set; }
[Required]
public string Name1 { get; set; }
public string Name2 { get; set; }
}
And my Address model is here:
public class Address : Model
{
[Required]
public string Street { get; set; }
[Required]
public string ZipCode { get; set; }
[Required]
public string City { get; set; }
public string Country { get; set; }
public string Email { get; set; }
}
They all inherit from "Model". Model has just an id.
Everything works well, BUT:
Lazy loading seems to be not working.
I'm loading a consignor like this:
List<Consignor> consignors = UnitOfWork.ConsignorRepository.Get().ToList();
All of the consignors got the correct AddressID and Address is not null (I guess because of my constructor in the Consignor class) but the Address property is not filled correctly (no street, no zip code, etc.).
It looks like the Consignor's constructor will instantiate a new Address object with blank street, zip, etc. (like you mentioned in your last paragraph); if you remove the instantiation of Address, you should end up with a not-loaded Address on your Consignor objects that you can lazily load as needed.
I'm busy creating my first EF code first model and I've come across a slightly confusing problem.
I have a number of model classes that each inherit from a base model class that has three common properties I want used in all model classes. These properties are Id, LastUpdated and LastUpdatedBy.
Id is the primary key of each model class.
LastUpdated is a foreign key to my 'User' model class.
LastUpdatedBy is a datetime field that indicates the last time the record was modified.
So what I'd like to setup is the 1 to 1 foreign key relationship from my base class to my 'User' model class but I'm receiving the exception:
Multiplicity is not valid in Role 'Profile_LastUpdatedByUser_Source'
in relationship 'Profile_LastUpdatedByUser'. Because the Dependent
Role properties are not the key properties, the upper bound of the
multiplicity of the Dependent Role must be '*'
This is my ModelBase class:
public class ModelBase
{
public int Id { get; set; }
public DateTime LastUpdated { get; set; }
[ForeignKey("LastUpdatedByUser")]
[Required]
public int LastUpdatedByUserId { get; set; }
public virtual User LastUpdatedByUser { get; set; }
}
This is one of my model classes:
public class Profile : ModelBase
{
[StringLength(25, MinimumLength=1)]
[Required(ErrorMessage="First Name is Required")]
public string FirstName { get; set; }
[StringLength(25, MinimumLength = 1)]
[Required(ErrorMessage = "Last Name is Required")]
public string LastName { get; set; }
[StringLength(25, MinimumLength = 1)]
[Required(ErrorMessage = "Email Address is Required")]
public string Email { get; set; }
public string Mobile { get; set; }
public string HomePhone { get; set; }
public string WorkPhone { get; set; }
public string ImageSource { get; set; }
public Squable.Model.Enums.MembershipType.MembershipTypeEnum MembershipType { get; set; }
}
This is my user class (Please ignore the Password property, I'll fix that later ;) ):
public class User : ModelBase
{
public string UserName { get; set; }
public string Password { get; set; }
public int ProfileId { get; set; }
public virtual Profile Profile { get; set; }
}
I don't know if what I am doing is best practise but I could do with some advice as to how to either fix the problem or maybe just some pointers in the right direction.
Move
public int Id { get; set; }
to User class and to Profile you can also change the names to UserId and to ProfileId and move
public virtual User LastUpdatedByUser { get; set; }
to Profile class.
I have a bad experience with sharing Id in base entity If you are planning to use Repository and UnitOfWork pattern you will get a lot of problems later. Check your current database structure and tables with SQL Server Management Studio.
More Info TPH
Bear with me as I'm new to C# and programming in general.
I'm trying to define a complex type that is in the same table as the principle class. Basically, it's the good old User and Address example.
public class Customer
{
[Key]
public int customerId { get; set; }
//some attributes
public string street { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string postal { get; set; }
}
So I try to slice off the address information into its own class:
public class Customer
{
[Key]
public int customerId { get; set; }
//some attributes
public Address address { get; set; }
}
[ComplexType]
public class Address
{
public string street { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string postal { get; set; }
}
I get no compile error and when I load a view that access the Customer model, I get an unknown column in field set error.
Unknown column 'Extent1.address_street' in 'field list'
I basically followed this example: http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx
Is there something I"m missing or something different with EF5?
By default EF expects columns for properties of complex types in form {complextypename_propertyname}. If you created your tables manually and named columns differently there will be a mismatch. Can you try renaming the columns accordingly (i.e. street to address_street) and try if it works. Alternatively you should be able to add an attribute to the properties on the complex type to tell EF that is should not use the convention but the name you specified (e.g. [Column("street")] for the street property).