How do I validate & potentially charge Credit Card details server side (in the Create function below) without saving these details to a database.
Create ActionResult
public ActionResult Create()
{
var model = new Payment();
model.ValidFrom = DateTime.Now;
return View(new Payment());
}
// POST: Payments/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,CardName,CardNumber,ValidFrom,Expires,CardSecurityCode,EmailAddress,ConfrimEmailAddress,Address,City,Country,PostCode")] PaymentViewModel paymentViewModel ,Payment payment)
{
if (ModelState.IsValid)
{
payment = new Payment();
payment.EmailAddress = paymentViewModel.EmailAddress;
payment.ConfrimEmailAddress = paymentViewModel.ConfirmEmailAddress;
payment.Address = paymentViewModel.Address;
payment.City = paymentViewModel.City;
payment.Country = paymentViewModel.Country;
payment.PostCode = paymentViewModel.PostCode;
db.Payments.Add(payment);
db.SaveChanges();
return RedirectToAction("Details", "Payments", new { id = payment.ID });
}
return View(paymentViewModel);
}
Model
public class Payment
{
public int ID { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string CardName { get; set; }
// ------------------------------Visa Card ---------------------------------------------//
[RegularExpression(#"^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})|(4903|4905|4911|4936|6333|6759)[0-9]{12}|(4903|4905|4911|4936|6333|6759)[0-9]{14}|(4903|4905|4911|4936|6333|6759)[0-9]{15}|564182[0-9]{10}|564182[0-9]{12}|564182[0-9]{13}|633110[0-9]{10}|633110[0-9]{12}|633110[0-9]{13}$", ErrorMessage = "Invalid Card Number You Paki")]
public string CardNumber { get; set; }
[Display(Name = "Valid From"), DataType(DataType.Date) DisplayFormat(DataFormatString = "{0:MM}")]
public DateTime ValidFrom { get; set; }
[Display(Name = "Valid From"), DataType(DataType.Date) DisplayFormat(DataFormatString = "{0:MM}")]
public DateTime Expires { get; set; }
public string CardSecurityCode { get; set; }
[Required]
[EmailAddress]
public string EmailAddress { get; set; }
[Compare("EmailAddress", ErrorMessage = "The email and confirmation email do not match.")]
public string ConfrimEmailAddress { get; set; }
[RegularExpression(#"([a-zA-Z0-9\s]+)", ErrorMessage = "Invalid Address")]
public string Address { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string City { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string Country { get; set; }
[RegularExpression(#"\b\d{5}(?:-\d{4})?\b+", ErrorMessage = "Invalid postcode")]
public string PostCode { get; set; }
}
public class PaymentDBContext : DbContext //controls information in database
{
public DbSet<Payment> Payments { get; set; } //creates a donation database
public System.Data.Entity.DbSet<CharitySite.Models.Charity> Charities { get; set; }
}
I need to be able to retrive the Credit Card numbers without storing them in the database. Our original idea was to validate Credit Card Details client side using Javascript but project requirements dictate that server sided validation is performed.
If you only need to save a part of the information, and use the rest only for validation purposes (eg, validate the number of credit card), then you must use a ViewModel that contains all the information requested on the form, and extract from the ViewModel only the information you need save:
ViewModel:
public class PaymentViewModel
{
public int ID { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string CardName { get; set; }
// ------------------------------Visa Card ---------------------------------------------//
[RegularExpression(#"^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})|(4903|4905|4911|4936|6333|6759)[0-9]{12}|(4903|4905|4911|4936|6333|6759)[0-9]{14}|(4903|4905|4911|4936|6333|6759)[0-9]{15}|564182[0-9]{10}|564182[0-9]{12}|564182[0-9]{13}|633110[0-9]{10}|633110[0-9]{12}|633110[0-9]{13}$", ErrorMessage = "Invalid Card Number You Paki")]
public string CardNumber { get; set; }
[Display(Name = "Valid From"), DataType(DataType.Date) DisplayFormat(DataFormatString = "{0:MM}")]
public DateTime ValidFrom { get; set; }
[Display(Name = "Valid From"), DataType(DataType.Date) DisplayFormat(DataFormatString = "{0:MM}")]
public DateTime Expires { get; set; }
public string CardSecurityCode { get; set; }
[Required]
[EmailAddress]
public string EmailAddress { get; set; }
[Compare("EmailAddress", ErrorMessage = "The email and confirmation email do not match.")]
public string ConfrimEmailAddress { get; set; }
[RegularExpression(#"([a-zA-Z0-9\s]+)", ErrorMessage = "Invalid Address")]
public string Address { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string City { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string Country { get; set; }
[RegularExpression(#"\b\d{5}(?:-\d{4})?\b+", ErrorMessage = "Invalid postcode")]
public string PostCode { get; set; }
}
Model (only containing fields to save):
public class Payment
{
public int ID { get; set; }
[Required]
[EmailAddress]
public string EmailAddress { get; set; }
[Compare("EmailAddress", ErrorMessage = "The email and confirmation email do not match.")]
public string ConfrimEmailAddress { get; set; }
[RegularExpression(#"([a-zA-Z0-9\s]+)", ErrorMessage = "Invalid Address")]
public string Address { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string City { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string Country { get; set; }
[RegularExpression(#"\b\d{5}(?:-\d{4})?\b+", ErrorMessage = "Invalid postcode")]
public string PostCode { get; set; }
}
public class PaymentDBContext : DbContext //controls information in database
{
public DbSet<Payment> Payments { get; set; } //creates a donation database
public System.Data.Entity.DbSet<CharitySite.Models.Charity> Charities { get; set; }
}
Create Action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(PaymentViewModel paymentViewModel)
{
if (ModelState.IsValid)
{
// Some validation on credit card before save payment...
// Save payment
payment = new Payment();
payment.EmailAddress = paymentViewModel.EmailAddress;
payment.ConfirmEmailAddress = paymentViewModel.ConfirmEmailAddress;
payment.Address = paymentViewModel.Address;
payment.City = paymentViewModel.City;
payment.Country = paymentViewModel.Country
payment.PostCode = paymentViewModel.PostCode;
db.Payments.Add(payment);
db.SaveChanges();
return RedirectToAction("Details", "Payments", new { id = payment.ID });
}
return View(paymentViewModel);
}
And change the Model used in your View:
#model [yourNameSpace].paymentViewModel
As far as I am aware there is no legislation actively prohibiting you from storing Credit Card details. Though certain aspects of your implementation may fail PCI compliance. For example, you may store the credit card number and expiry date but this must be in an encrypted form, you may NEVER store the CCV in any form.
Either way it isn't really recommended that you take on the burden of storing CC numbers, unless you have considerable experience and compliance budget. The only advantage I can really see to this is the consumer convenience of not having to repeatedly enter details. Most payment processors should allow you pass details to them for charging. If you choose this approach you may want to look into usage of the SecureString class which will allow you to dispose of details as soon as you have transmitted them to the processor.
Related
This seems to be a common question. I have looked at many examples however I must be missing something somewhere. Below is my code for the 'ViewModel', and 'Controller'.
ViewModel:
public class EditAddressViewModel
{
public Guid AddressUI { get; set; }
[Display(Name = "Billing Address?")]
[UIHint("_IsStatus")]
public bool IsBilling { get; set; }
[Display(Name = "Shipping Address?")]
[UIHint("_IsStatus")]
public bool IsShipping { get; set; }
[Display(Name = "Location Name")]
public string LocationName { get; set; }
[Display(Name = "Contact Name")]
public string ContactName { get; set; }
[Display(Name = "Address")]
public string Line1 { get; set; }
[Display(Name = "Address 2")]
public string Line2 { get; set; }
[Display(Name = "Country")]
public int Country { get; set; }
[Display(Name = "State")]
public int State { get; set; }
[Display(Name = "City")]
public int City { get; set; }
[Display(Name = "ZipCode")]
public string ZipCode { get; set; }
[Display(Name = "Contact Email")]
[DataType(DataType.EmailAddress)]
[StringLength(320)]
[RegularExpression(#"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", ErrorMessage = "Enter a valid email address")]
public string EmailAddress { get; set; }
[Display(Name = "Phone Number")]
[DataType(DataType.PhoneNumber)]
[StringLength(12)]
[RegularExpression(#"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Enter a valid phone number")]
public string PhoneNumber { get; set; }
[Display(Name = "Fax Number")]
[DataType(DataType.PhoneNumber)]
[StringLength(12)]
[RegularExpression(#"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Enter a valid phone number")]
public string FaxNumber { get; set; }
public int CompanyId { get; set; }
[Display(Name = "Select Country")]
public int CountryId { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
[Display(Name = "Select State")]
public int StateId { get; set; }
public IEnumerable<SelectListItem> States { get; set; }
[Display(Name = "Select Cit;y")]
public int CityId { get; set; }
public IEnumerable<SelectListItem> Cities { get; set; }
}
The Controller:
// Customer Input
// GET: Addresses/Edit/5
[Authorize(Roles = "CompanyAdmin")]
public ActionResult UserEdit(Guid guid)
{
if (guid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Addresses addresses = db.Addresses.Find(guid);
if (addresses == null)
{
return HttpNotFound();
}
EditAddressViewModel editAddress = new EditAddressViewModel()
{
AddressUI = addresses.AddressUI,
LocationName = addresses.LocationName,
Line1 = addresses.Line1,
Line2 = addresses.Line2,
Country = addresses.Country,
State = addresses.State,
City = addresses.City,
ZipCode = addresses.ZipCode,
PhoneNumber = addresses.PhoneNumber,
FaxNumber = addresses.FaxNumber,
CompanyId = addresses.CompanyId
};
ConfigureViewModel(editAddress);
return View(editAddress);
}
public void ConfigureViewModel(EditAddressViewModel editAddressViewModel)
{
editAddressViewModel.Countries = db.Countries.Select(o => new SelectListItem()
{
Value = o.CountryId.ToString(),
Text = o.CountryName
});
editAddressViewModel.States = db.States.Select(o => new SelectListItem()
{
Value = o.StateId.ToString(),
Text = o.StateName
});
editAddressViewModel.Cities = db.Cities.Select(o => new SelectListItem()
{
Value = o.CityId.ToString(),
Text = o.CityName
});
}
// POST: Addresses/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UserEdit(EditAddressViewModel model)
{
var userId = User.Identity.GetUserId();
if (!ModelState.IsValid)
{
return View(model);
}
Addresses addresses = db.Addresses.Find(model.AddressUI);
addresses.IsBilling = EditAddressViewModel.IsBilling;
addresses.IsShipping = EditAddressViewModel.IsShipping;
addresses.LocationName = EditAddressViewModel.LocationName;
addresses.Line1 = EditAddressViewModel.Line1;
addresses.Line2 = EditAddressViewModel.Line2;
addresses.Country = EditAddressViewModel.Country;
addresses.State = EditAddressViewModel.State;
addresses.City = EditAddressViewModel.City;
addresses.ZipCode = EditAddressViewModel.ZipCode;
addresses.PhoneNumber = EditAddressViewModel.PhoneNumber;
addresses.FaxNumber = EditAddressViewModel.FaxNumber;
addresses.CompanyId = EditAddressViewModel.CompanyId;
db.Entry(addresses).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Customer", new { UserId = userId });
}
The issue I am running into is in the controller. All of the entries for Example
addresses.IsBilling = EditAddressViewModel.IsBilling;
Show that "An object reference is required for the non-static field, method, or property". If I go to my 'ViewModel' and change the "public int or string" to be "public static int" then it goes away but then I get an error on the get Action that is cannot be tied to a static object. I am a little confused because this same scenario seems to work for another question on this site. In mine it does not. I have to be missing something somewhere. thanks for your help.
When you say addresses.IsBilling = EditAddressViewModel.IsBilling; you are asking for a property of the class EditAddressViewModel
You want to access a property of the object model. So I think you want addresses.IsBilling = model.IsBilling; etc.
I am building an MVC app in ASP.Net and I want to combine my user model with my address model for registration purposes. Now I need to know how to implement the ViewModel for this. I am using code first and I am a beginner.
Below is the code for my two models and the db context.
public class SiteDataModel : DbContext
{
// Your context has been configured to use a 'SiteDataModel' connection string from your application's
// configuration file (App.config or Web.config). By default, this connection string targets the
// 'WMVC.SiteDataModel' database on your LocalDb instance.
//
// If you wish to target a different database and/or database provider, modify the 'SiteDataModel'
// connection string in the application configuration file.
public SiteDataModel()
: base("name=SiteDataModel")
{
}
// Add a DbSet for each entity type that you want to include in your model. For more information
// on configuring and using a Code First model, see http://go.microsoft.com/fwlink/?LinkId=390109.
public virtual DbSet<Web_User> WebUsers { get; set; }
public virtual DbSet<Web_User_Address> WebUserAddresses { get; set; }
}
public class Web_User
{
[Key]
public int User_Id { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Email")]
[DataType(DataType.EmailAddress, ErrorMessage = "Please enter a valid e-mail address")]
public string Email { get; set; }
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Cellphone Number")]
[DataType(DataType.PhoneNumber)]
public string CellPhoneNumber { get; set; }
[Display(Name = "Date of Birth")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime DateOfBirth { get; set; }
public int Address_Id { get; set; }
public virtual Web_User_Address UserAddresses { get; set; }
}
public class Web_User_Address
{
[Key]
public int Address_Id { get; set; }
[Required]
[Display(Name="Postal Address")]
[DataType(DataType.PostalCode)]
public int PostalCode { get; set; }
[Required]
public string Street { get; set; }
public string Province { get; set; }
public ICollection<Web_User> WebUsers { get; set; }
}
A few pointers, you might need to update your Web_User_Address, to exclude "WebUsers" and have 1 userID, and your web_user Dbset should not have any addresslink( or adress ID)
look at it this way: one user can have many addresses. even if that is not the case in your program.
Accessing the two DbSets in the viewmodel, you can do something like this:
class RegistrationViewModel
{
SiteDataModel db = new SiteDataModel();
public AddUserAndAddress(Web_User_Address address, Web_User user){
//Note: address has a userId
var user = db.Web_User.First(a => a.Name== user.Name && /*etc*/ );
if(user != null){
// User already exists. Do something about that here
}
db.Web_User_Address.Add(address);
db.Web_User.Add(user);
db.SaveChanges();
}
}
I hope this helps. best of luck!
After re-reading your question. I finally understood what you asked.
The simple way to do this is to create a model with both Dbsets :)
I have an ASP.NET MVC website that is passing ViewModels up to a WebAPI Service in order to perform CRUD operations on objects in the database using Entity Framework code first.
One of my Domain Entity Objects is a Business, which has business information, an address, a primary contact, and secondary contact. The thing is, the secondary contact object is not required since not all companies will have a secondary contact. I have setup the ID field as nullable, but when I attempt to save a new business record into the database that doesn't have a secondary contact object, it is giving me entity validation errors that the Secondary Contact record fields are required.
Does anyone know how to stop this error so I can save the business entity in the database without a secondary contact?
Below is the related code. I am using automapper to map between my viewmodels and models.
Domain Business Object
public class Business
{
public Guid PrimaryContactId { get; set; }
[ForeignKey("PrimaryContactId")]
[Required]
public virtual Contact PrimaryContact { get; set; }
public Guid? SecondaryContactId { get; set; }
[ForeignKey("SecondaryContactId")]
public virtual Contact SecondaryContact { get; set; }
[Key]
public Guid Id { get; set; }
[Required]
[MaxLength(100)]
public string CompanyName { get; set; }
[MaxLength(100)]
public string CompanyWebsite { get; set; }
[Required]
[MaxLength(100)]
public string Industry { get; set; }
[Required]
public NumberOfEmployees NumberOfEmployees { get; set; }
[Required]
public CommunicationPreference CommunicationPreference { get; set; }
public Guid AddressId { get; set; }
[ForeignKey("AddressId")]
[Required]
public virtual Address Address { get; set; }
}
Business View Model
public class BusinessViewModel
{
public Guid PrimaryContactId { get; set; }
public PrimaryContactViewModel PrimaryContact { get; set; }
public Guid? SecondaryContactId { get; set; }
public SecondaryContactViewModel SecondaryContact { get; set; }
public Guid Id { get; set; }
[DisplayName("Company Name")]
[Required]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public string CompanyName { get; set; }
[DisplayName("Company Website")]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public string CompanyWebsite { get; set; }
[DisplayName("Industry")]
[Required]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public string Industry { get; set; }
[DisplayName("Number of Employees")]
[Required]
public NumberOfEmployees NumberOfEmployees { get; set; }
[DisplayName("Communication Preference")]
[Required]
public CommunicationPreference CommunicationPreference { get; set; }
public Guid AddressId { get; set; }
[Required]
public AddressViewModel Address { get; set; }
}
Domain Contact Object
public class Contact
{
[Key]
public Guid Id { get; set; }
[Required]
public Salutations? Prefix { get; set; }
[Required]
[MaxLength(100)]
public string FirstName { get; set; }
[Required]
[MaxLength(100)]
public string LastName { get; set; }
[Required]
[MaxLength(100)]
public string JobTitle { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[MaxLength(100)]
public string Email { get; set; }
[Required]
[MaxLength(100)]
public string Phone { get; set; }
[MaxLength(100)]
public string PhoneExtension { get; set; }
}
Base Contact View Model
public class BaseContactViewModel
{
public Guid Id { get; set; }
[DisplayName("Primary Contact Prefix")]
public virtual Salutations Prefix { get; set; }
[DisplayName("Primary Contact First Name")]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public virtual string FirstName { get; set; }
[DisplayName("Primary Contact Last Name")]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public virtual string LastName { get; set; }
[DisplayName("Primary Contact Job Title")]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public virtual string JobTitle { get; set; }
[DisplayName("Primary Contact Email Address")]
[DataType(DataType.EmailAddress)]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public virtual string Email { get; set; }
[DisplayName("Primary Contact Phone")]
[DataType(DataType.PhoneNumber)]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public virtual string Phone { get; set; }
[DisplayName("Primary Contact Extension")]
[MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
[MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
public virtual string PhoneExtension { get; set; }
}
Secondary Contact View Model
public class SecondaryContactViewModel : BaseContactViewModel
{
[DisplayName("Secondary Contact Prefix")]
public override Salutations Prefix { get; set; }
[DisplayName("Secondary Contact First Name")]
public override string FirstName { get; set; }
[DisplayName("Secondary Contact Last Name")]
public override string LastName { get; set; }
[DisplayName("Secondary Contact Job Title")]
public override string JobTitle { get; set; }
[DisplayName("Secondary Contact Email Address")]
public override string Email { get; set; }
[DisplayName("Secondary Contact Phone")]
public override string Phone { get; set; }
[DisplayName("Secondary Contact Extension")]
public override string PhoneExtension { get; set; }
}
Method that does the EF saving
public async Task<bool> CreateBusinessAsync(BusinessViewModel businessViewModel)
{
try
{
// TODO: Move mapping to some common place?
Mapper.CreateMap<BusinessViewModel, Business>();
Mapper.CreateMap<BaseContactViewModel, Contact>();
Mapper.CreateMap<AddressViewModel, Address>();
Business business = Mapper.Map<Business>(businessViewModel);
//TODO: See why EntityFramework isn't automatically putting in GUIDs
business.Id = Guid.NewGuid();
business.Address.Id = Guid.NewGuid();
business.PrimaryContact.Id = Guid.NewGuid();
// Attach the objects so they aren't saved as new entries
db.States.Attach(business.Address.State);
db.Countries.Attach(business.Address.Country);
//TODO: See why entity framework isn't automatically saving records
var bus = db.Businesses.Add(business);
var primary = db.Contacts.Add(business.PrimaryContact);
if (!String.IsNullOrEmpty(business.SecondaryContact.FirstName))
{
business.SecondaryContact.Id = Guid.NewGuid();
db.Contacts.Add(business.SecondaryContact);
}
else
{
business.SecondaryContact = null;
}
var address = db.Addresses.Add(business.Address);
int rowsAffected = await db.SaveChangesAsync();
if (bus != null && rowsAffected > 0)
{
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
//TODO: Add exception logger
string error = e.Message;
return false;
}
}
Please let me know if it would be useful to see any other classes. Thanks.
I had a similar issue before and the way I fixed it was by taking the foreign key data annotation off of the property and using fluent-api. Using fluent-api I just labeled the correct side of the relationship as optional.
You can just make the data type to nullable based on documentation
public class Foo {
// ...... Some property
[ForeignKey("tagId")]
public ICollection<SomeModel>? data {get; set;}
}
This will make the property not validated and return validated result. Using Model.IsValid
I am new to MVC 3 Data Annotations and I just want to ask that if its possible to add Validation on a Group of Fields in Model and Display the validation if none of it has Value?
this is the set of fields in my Data model
public class ContactModel
{
public Nullable<int> Id { get; set; }
[Display(Name = "Contact Firstname")]
[Required(ErrorMessage = "Required!")]
public string ContactFirstname { get; set; }
[Display(Name = "Contact Lastname")]
[Required(ErrorMessage = "Required!")]
public string ContactLastname { get; set; }
[Display(Name = "Contact Middlename")]
public string ContactMiddlename { get; set; }
[Display(Name = "Phone")]
[Required(ErrorMessage = "Required!")]
public string ContactPhone { get; set; }
[Display(Name = "Mobile ")]
[Required(ErrorMessage = "Required!")]
public string ContactMobile { get; set; }
[Display(Name = "Email")]
[Required(ErrorMessage = "Required!")]
public string ContactEmail { get; set; }
[Display(Name = "Job Title")]
[StringLength(50, ErrorMessage = "Max character reached!")]
public string ContactJobTitle { get; set; }
}
And I want to add validation if one from Phone,Mobile or Email doesn't have value
Thanks
You can implement IValidatableObject interface and add validation for all necessary properties:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(string.IsNullOrEmpty(Phone) || string.IsNullOrEmpty(Mobile) || string.IsNullOrEmpty(Email))
{
yield return new ValidationResult("Some error message");
}
}
Of course you should remove [Required] attributes then from those properties.
I had been struggling with this issue since morning. I have the following class in my domain service.
[MetadataTypeAttribute(typeof(CompanyRecord.CompanyRecordMetadata))]
public partial class CompanyRecord
{
// This class allows you to attach custom attributes to properties
// of the CompanyRecord class.
//
// For example, the following marks the Xyz property as a
// required property and specifies the format for valid values:
// [Required]
// [RegularExpression("[A-Z][A-Za-z0-9]*")]
// [StringLength(32)]
// public string Xyz { get; set; }
internal sealed class CompanyRecordMetadata
{
// Metadata classes are not meant to be instantiated.
private CompanyRecordMetadata()
{
}
public Nullable<char> AccessToClearance { get; set; }
public Nullable<char> AccessToMarketplace { get; set; }
public Nullable<bool> Active { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public Nullable<int> AllotedHDSpace { get; set; }
public string City { get; set; }
public int CompanyID { get; set; }
public Binary CompanyLogo { get; set; }
[Required(ErrorMessage = "Company Name is required and must be unique.")]
public string CompanyName { get; set; }
[Range(1, Int32.MaxValue, ErrorMessage = "Company Type is required.")]
public int CompanyTypeID { get; set; }
[Range(1, Int32.MaxValue, ErrorMessage = "Country is required.")]
public Nullable<int> CountryID { get; set; }
public string Description { get; set; }
//[RegularExpression(pattern: #"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|tv|COM|ORG|NET|GOV|MIL|BIZ|INFO|MOBI|NAME|AERO|JOBS|MUSEUM|TV|Com|Org|Net|Gov|Mil|Biz|Info|Mobi|Name|Aero|Jobs|Museum|Tv)\b", ErrorMessage = "Please provide a valid email address")]
[RegularExpression(pattern: #"(\w[-._\w]*\w#\w[-._\w]*\w\.[a-zA-z]{2,6})", ErrorMessage = "Please provide a valid email address")]
public string EmployeeEmail { get; set; }
//[RegularExpression(pattern: #"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|tv|COM|ORG|NET|GOV|MIL|BIZ|INFO|MOBI|NAME|AERO|JOBS|MUSEUM|TV|Com|Org|Net|Gov|Mil|Biz|Info|Mobi|Name|Aero|Jobs|Museum|Tv)\b", ErrorMessage = "Please provide a valid email address")]
//(\w[-._\w]*\w#\w[-._\w]*\w\.\w{2,3})
[RegularExpression(pattern: #"(\w[-._\w]*\w#\w[-._\w]*\w\.[a-zA-z]{2,6})", ErrorMessage = "Please provide a valid email address")]
[Required(ErrorMessage = "Email is required.")]
public string Email { get; set; }
[StringLength(10, ErrorMessage = "Phone Ext. should not be more than 10 chars.")]
public string EmployeePhoneExt { get; set; }
[StringLength(20, ErrorMessage = "Phone No. should not be more than 20 chars.")]
[RegularExpression(pattern: #"^[0-9\-\(\) ]*[0-9\-\(\)]*$", ErrorMessage = "Please provide a valid Phone No.")]
public string EmployeePhoneNo { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Range(0, int.MaxValue, ErrorMessage = "Number of projects should be lower than 2,147,483,647.")]
public Nullable<int> NoOfProjects { get; set; }
public Nullable<int> NoOfUsers { get; set; }
[StringLength(10, ErrorMessage = "Phone Ext. should not be more than 10 chars.")]
public string PhoneExt { get; set; }
[StringLength(20, ErrorMessage = "Phone No. should not be more than 20 chars.")]
[Required(ErrorMessage = "Phone No. is required.")]
[RegularExpression(pattern: #"^[0-9\-\(\) ]*[0-9\-\(\)]*$", ErrorMessage = "Please provide a valid Phone No.")]
public string PhoneNo { get; set; }
[RegularExpression(pattern: #"^[a-zA-Z0-9\-\(\)\* ]*[a-zA-Z0-9\-\(\)\*]*$", ErrorMessage = "Postal codes cant' contain special characters except for -, (, ), * and spaces.")]
public string PostalCode { get; set; }
public string Province { get; set; }
public string Website { get; set; }
public int MarketID { get; set; }
public int AffiliationID { get; set; }
public string CallLetter { get; set; }
}
}
PROBLEM: I need to create a validation rule that woudl require MarketID and Affiliation ID only when CompanyTypeID is equivalent to 1, 3, 5, 9 and 11 is there someone out there who has an idea on how to solve this?
You should use the custom validation.
There are some topics for your question below:
1 http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.customvalidationattribute(vs.95).aspx
2 http://blogs.microsoft.co.il/blogs/bursteg/archive/2009/04/14/net-ria-services-custom-validation.aspx