I have one table np_user_dtls with 4 fields in sql server
user_name
user_last_name
arabic_name
nationality
In mvc i created a model class as below
public partial class np_user_dtls
{
[Display(Name = "First Name*")]
[Required(ErrorMessage = "First name is required.")]
public string user_name { get; set; }
[Required(ErrorMessage = "last name is required.")]
public string user_last_name { get; set; }
[Required(ErrorMessage = "arabic name is required.")]
public string arabic_name { get; set; }
[Required(ErrorMessage = "nationality is required.")]
public string nationality { get; set; }
}
and in context model i define the relationship between model class and db table as follow
public System.Data.Entity.DbSet<****.Models.np_user_dtls> np_user__dtls { get; set; }
now i need an another class in which arabic name is not mandatory
so i create a model like below
public partial class np_user_dtls_1
{
[Display(Name = "First Name*")]
[Required(ErrorMessage = "First name is required.")]
public string user_name { get; set; }
[Required(ErrorMessage = "last name is required.")]
public string user_last_name { get; set; }
[Required(ErrorMessage = "nationality is required.")]
public string nationality { get; set; }
}
but when i create an entry for this in db context like below
public System.Data.Entity.DbSet<****.Models.np_user_dtls_1> np_user__dtls { get; set; }
its giving me an error
The type ****.Models.***** already contains a definition for
np_user__dtls
is it not possible to define multiple model for a single table?
You can set one entity model for one table. then you can bind different view model with your entity model.
entity class.
public partial class np_user_dtls
{
public string user_name { get; set; }
public string user_last_name { get; set; }
public string arabic_name { get; set; }
public string nationality { get; set; }
}
you can use this class for database table.
public partial class np_user_dtls_response1
{
[Display(Name = "First Name*")]
[Required(ErrorMessage = "First name is required.")]
public string user_name { get; set; }
[Required(ErrorMessage = "last name is required.")]
public string user_last_name { get; set; }
[Required(ErrorMessage = "arabic name is required.")]
public string arabic_name { get; set; }
[Required(ErrorMessage = "nationality is required.")]
public string nationality { get; set; }
}
you can use this class as view model. accept request by this class. then map this class np_user_dtls and save information in db.
later you can use another view model class such as
public partial class np_user_dtls_response2
{
[Display(Name = "First Name*")]
[Required(ErrorMessage = "First name is required.")]
public string user_name { get; set; }
[Required(ErrorMessage = "last name is required.")]
public string user_last_name { get; set; }
[Required(ErrorMessage = "nationality is required.")]
public string nationality { get; set; }
}
bind this class again with class np_user_dtls and save information in db. In this you can use two kind of validation in application level save data in database. Previously you can set validation database level. thats why you cant set two class
Related
I want to add a country drop down list to my agent form, the database part has been created when running the migration but when I generate the controllers and the views, the drop down list won't generate
public class Agent
{
public int AgentID { get; set; }
[Required]
[Display(Name = "Social Insurance Number")]
public string SIN { get; set; }
public Country Country { get; set; }
[Required]
[Display(Name = "First Name")]
[StringLength(20, ErrorMessage = "First Name cannot be longer than 20 characters")]
public string FirstName { get; set; }
}
public class Country
{
public int ID { get; set; }
[Required]
[Display(Name = "Country")]
public countries Name { get; set; }
public ICollection<Agent> Agents { get; set; }
}
public enum countries
{
canada,
usa
}
I have a simple member registration data model with a few required properties and some optional properties. The BillToAddress property is optional.
public class MemberRegistration
{
[Required(ErrorMessage = "First Name is required.")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required.")]
public string LastName { get; set; }
[Required(ErrorMessage = "Email Address is required.")]
public string EmailAddress { get; set; }
public string PhoneNumber { get; set; }
[Required(ErrorMessage = "Password is required.")]
[MinLength(7, ErrorMessage = "Password must be at least 7 characters.")]
public string Password { get; set; }
private Address m_BillToAddress;
public Address BillToAddress
{
get
{
if (m_BillToAddress == null)
{
m_BillToAddress = new Address();
}
return m_BillToAddress;
}
}
}
If the user enters an optional bill to address, I would like the street, city, country, and postal code to be required. So I defined the Address data model, marking those properties as required.
public class Address
{
[Required(ErrorMessage = "Street Line 1 is required.")]
public string Street1 { get; set; }
public string Street2 { get; set; }
public string Street3 { get; set; }
public string Street4 { get; set; }
public string Street5 { get; set; }
[Required(ErrorMessage = "City is required.")]
public string City { get; set; }
[Required(ErrorMessage = "State or Province is required.")]
public string StateOrProvince { get; set; }
[Required(ErrorMessage = "Country is required.")]
public string Country { get; set; }
[Required(ErrorMessage = "Postal Code is required.")]
public string PostalCode { get; set; }
}
But now the model validation fails when I don't supply a bill to address. How can I annotate my models so that the bill to address is optional, but if it is supplied, then it has to include street, city, country, and postal code?
The problem was in MemberRegistration class. Because the BillToAddress property getter always returned a new, empty Address model, BillToAddress was never null and always correctly triggered the Address class validation. I changed BillToAddress to a simple auto-implemented property:
public Address BillToAddress { get; set; }
Now if I post a MemberRegistion without a BillToAddress, it passes validation because BillToAddress is an optional property.
I'm practicing with ASP.Net MVC 5, and I'm attempting to build a prototype events directory. I've started with a basic layout, adapted from the Contoso University tutorial, but I want to start to develop a more complex data model, however I'm unsure as to the best way to develop the model, specifically, the different pricing options each listing can have.
My current data model is;
Vendors
public class Vendor
{
public int ID { get; set; }
[Required]
[Display(Name = "Company Name")]
[StringLength(50, ErrorMessage = "Company name cannot be longer than 50 characters.")]
public string CompanyName { get; set; }
[Required]
[Display(Name = "First Name")]
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
public string ContactFirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
[StringLength(50, ErrorMessage = "Last name cannot be longer than 50 characters.")]
public string ContactLastName { get; set; }
[Required]
[Display(Name = "Address")]
public string Address { get; set; }
[Required]
[Display(Name = "Address Line 2")]
public string AddressLine2 { get; set; }
[Required]
public string Region { get; set; }
[Required]
public string City { get; set; }
[Required]
public string Postcode { get; set; }
[Required]
[Display(Name = "Email Address")]
public string Email { get; set; }
[Required]
[Display(Name = "Phone Number")]
public string Phone { get; set; }
[Display(Name = "Twitter #username")]
public string TwitterHandle { get; set; }
[Display(Name = "Facebook URL")]
public string FacebookURL { get; set; }
[Required]
[Display(Name = "Active Vendor?")]
public Boolean ActiveStatus { get; set; }
public virtual ICollection<Listing> Listings { get; set; }
}
Listings
public class Listing
{
public int ListingID { get; set; }
public int CategoryID { get; set; }
public int VendorID { get; set; }
[Required]
[Display(Name = "Listing Name")]
public string ListingName { get; set; }
[Required]
[Display(Name = "Listing Description")]
public string ListingDesc { get; set; }
[Required]
[Display(Name = "Maximum Capacity")]
public int Capacity { get; set; }
[Required]
[DataType(DataType.Currency)]
[Display(Name = "Price Per Guest")]
public decimal PricePerGuest { get; set; }
[Required]
public string Address { get; set; }
[Display(Name = "Address Line 2")]
public string Address2 { get; set; }
[Required]
public string City { get; set; }
[Required]
public string Postcode { get; set; }
public virtual Category Category { get; set; }
public virtual Vendor Vendor { get; set; }
}
Categories
public class Category
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public string CategoryDescription { get; set; }
public virtual ICollection<Listing> Listings { get; set; }
}
Ideally, I'd like to add to the Listing table a new property called 'Fixed Price', giving vendors the option to either list by price per guest or by fixed price, as not all vendors can price their services by price per guest.
Is a separate table with pricing options sufficient enough to develop this further?
P.S - I haven't yet started to format the entities properly yet, hence why categories is missing validation and so on.
Price (currency) and IsFixedPrice (bit) Instead of PricePerGuest
Thanks to #Nikhil Vartak for the answer
In the Checkout Controller I have the code
[HttpPost]
public ActionResult AddressAndPayment(FormCollection values)
{
var order = new Order();
TryValidateModel(order);
....
The model looks like this
[Bind(Exclude="OrderId")]
public partial class Order
{
[ScaffoldColumn(false)]
public int OrderId { get; set; }
[ScaffoldColumn(false)]
public string Username { get; set; }
[Required(ErrorMessage= "First Name is required")]
[DisplayName("First Name")]
[StringLength(160)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required")]
[DisplayName("Last Name")]
[StringLength(160)]
public string LastName { get; set; }
[Required(ErrorMessage="Address is required")]
[StringLength(70)]
public string Address { get; set; }
[Required(ErrorMessage = "City is required")]
[StringLength(40)]
public string City { get; set; }
[Required(ErrorMessage = "State is required")]
[StringLength(40)]
public string State { get; set; }
[Required(ErrorMessage = "Postal Code is required")]
[DisplayName("Postal Code")]
[StringLength(10)]
public string PostalCode { get; set; }
[Required(ErrorMessage="Country is required")]
[StringLength(40)]
public string Country { get; set; }
[Required(ErrorMessage= "Phone is required")]
[StringLength(24)]
public string Phone { get; set; }
[Required(ErrorMessage="Email Address is required")]
[DisplayName("Email Address")]
[RegularExpression(#"[A-za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage="Email is not valid.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[ScaffoldColumn(false)]
public decimal Total { get; set; }
[ScaffoldColumn(false)]
public DateTime OrderDate { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
}
I can stop right before the TryValidateModel line and look at form values like
? Request.Form["FirstName"]
"Michael"
? values["FirstName"]
"Michael"
So why does TryValidateModel(order); return false and the order object does not get populated?
Update
To clarify my question I know false means it can not bind but I do not know why it can not bind. Or that it should through the TryValidateModel(or even the ValidateModel)
But what is interesting is that if I change my method signature to
public ActionResult AddressAndPayment(Order order)
order gets populated correctly. So if it is able to bind in the Method call why not TryValidateModel(or even the ValidateModel)?
I am using MVC 4
TryValidateModel returns false when validation of the Form Model against your Orders Model Fails, thus Binding fails.
I hate using
TryValidateModel(order);
and prefer
ValidateModel(order);
early on while developing my page, because binding is a delicate process. This way, if the model fails to bind, I get an exception and an indicative error msg.
I am wondering what is the correct way to approach this. I currently have one model - (shown below), which contains all the fields required for my record.
My issue is that when the record is created I only need to pass data for
CustomerID, EmployeeID, Date and ArrivalTime.
The remainder of the fields in the model will be populated when the record is updated at a later stage.
As some of my fields are required this will obviously cause validation errors if I don't post data for those fields.
I am wondering what is the best practice to achieve this?
Should I split the model into two?, or can I do partial validation?
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; }
[Required(ErrorMessage = "Please select a Departure Time")]
[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; }
[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; }
}
The correct approach would be to use different viewmodel classes for the different views and only include the properties you need on that view.
So your viewmodel for the first view look just like this:
public class CustomerSupportRecordForCreation
{
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; }
}
You will have to map between that viewmodel classes and your domain/dal classes. This is where tools like AutoMapper comes in handy.
Edit Automapper:
Using Automapper is really simple.
You have to configure your mappings (i.e. in Application_Start). When the properties of the classes you want to map are named identically, its simple as this:
Mapper.CreateMap<CustomerSupportRecord,
CustomerSupportRecordForCreation>();
Then you can use the mapped in your app. When you have a CustomerSupportRecord and want to return the CustomerSupportRecordForCreation for your view write:
CustomerSupportRecord record = getRecordFromDb...
return View(Mapper.Map<CustomerSupportRecordForCreation>(record));
There is a good tutorial article on Codeproject: http://www.codeproject.com/Articles/61629/AutoMapper or just google