This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I have NullReferenceException error in forgotten password section. Where is my mistake and how can I fix it? Here are my codes:
my controller :
public ActionResult ForGotPasswordSent(ForGotModel forgetModel)
{
User user = _userService.GetUserByEmail(forgetModel.Email);
if (user.IsActive)
{
var objEmail = new EmailHelper();
Message msg = new Message();
msg.SuccessMessage = "You have sent the mail,Please verify that";
msg.IsSuccess = true;
string strBody = "Thanks for using the forgot password function.You need to set new password to your account, please click here to proceed";
bool result = objEmail.SendMail("noreply#xx.com", "xxtest#gmail.com", "", "Activate Your Account", strBody, true);
if (result)
return View("Activation", msg);
else
return View("Activation");
}
else
{
this.ModelState.AddModelError("", "You have to activate your account");
return View("Activation");
}
}
my User class:
public class User : IPrincipal
{
public int Id { get; set; }
[Required(ErrorMessage = "Kullanıcı adı girilmesi zorunludur.")]
[Display(Name = "Kullanıcı Adı")]
public string Username { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Required(ErrorMessage = "Password Required")]
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; }
public bool IsActive { get; set; }
public bool IsAdmin { get; set; }
public bool IsDeleted { get; set; }
public DateTime? CreatedDate { get; set; }
public DateTime? ModifiedDate { get; set; }
my ForgotModel
public class ForGotModel
{
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
}
_userService.GetUserByEmail method:
public User GetUserByEmail(string email)
{
var user = _userRepository.Get(x => x.Email == email);
return user;
}
You probably will want to add a null check to user before checking the IsActive property. Try this:
if (user != null && user.IsActive)
GetUserByEmail might return null, when no user is found. Verify that your User object is not null before checking for user.IsActive.
Related
I'm new to .Net and I need your help. I'm using code first approach for my project and I'm trying to build custom register/login with encryption. By some reason I cannot save the user in my database when trying to encrypt the password. Saving the user in the database works when I remove the 2 lines for encryption and salting. Here is my User model:
public class User
{
[Key]
public int UserId { get; set; }
[Required(ErrorMessage = "First Name is required !")]
[Display(Name = "First Name: ")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required !")]
[Display(Name = "Last Name: ")]
public string LastName { get; set; }
[Required(ErrorMessage = "Email is required !")]
[EmailAddress]
[StringLength(50)]
[RegularExpression(#"^([\w\.\-]+)#([\w\-]+)((\.(\w){2,3})+)$", ErrorMessage = "Please enter valid email")]
[Display(Name = "Email Address: ")]
public string Email { get; set; }
[StringLength(50)]
[Display(Name = "Company Name: ")]
public string CompanyName { get; set; }
[Required(ErrorMessage = "Password is required !")]
[DataType(DataType.Password)]
[Display(Name = "Password: ")]
public string Password { get; set; }
[NotMapped]
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "Passwords don't match !")]
public string ConfirmPassword { get; set; }
public string PasswordSalt { get; set; }
public int AdminCode { get; set; }
}
And here is my Register method in my controller:
[HttpPost]
public ActionResult Register(Models.User user)
{
if (ModelState.IsValid)
{
using (AppContext db = new AppContext())
{
var crypto = new SimpleCrypto.PBKDF2();
var encrypPass = crypto.Compute(user.Password);
//var newUser = db.Users.Create();
//newUser.FirstName = user.FirstName;
//newUser.LastName = user.LastName;
//newUser.Email = user.Email;
//newUser.CompanyName = user.CompanyName;
//newUser.Password = encrypPass;
//newUser.PasswordSalt = crypto.Salt;
//newUser.AdminCode = 0;
user.Password = encrypPass;
user.PasswordSalt = crypto.Salt;
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Data is not correct");
}
return View();
}
Here is my table.. When trying to encrypt I get Error "Validation failed for one or more entities.", but I have no idea what validation is failing. I've checked my DB table and the User model and I don't see the problem. I've really tried to figure it out by my own, but I can't! Any ideas what am I missing ? Thanks in advance.
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.
I need to store additional information during user registration such as: First Name, Last Name and etc.
My question has two parts:
How can I save my additional information during Register?
My current method throws error:
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
I have already checked "Watch" inside VS and also used try-catch but it didn't help.
Thanks in advance for your help!
IdentityModels.cs
public class ApplicationIdentityAccount : IdentityUser
{
public virtual ICollection<AccountProfile> AccountProfiles { get; set; }
}
public class AccountProfile
{
[Key]
public string AccountProfileID { get; set; }
[DisplayName("First Name")]
[StringLength(50)]
[Required(ErrorMessage = "First name is required")]
public string FirstName { get; set; }
[DisplayName("Middle Name")]
[StringLength(50)]
public string MiddleName { get; set; }
[DisplayName("Last Name")]
[StringLength(50)]
[Required(ErrorMessage = "Last name is required")]
public string LastName { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationIdentityAccount User { get; set; }
}
public class ApplicationIdentityDbContext : IdentityDbContext<ApplicationIdentityAccount>
{
public ApplicationIdentityDbContext()
: base("ApplicationIdentity", throwIfV1Schema: false)
{
}
public static ApplicationIdentityDbContext Create()
{
return new ApplicationIdentityDbContext();
}
public System.Data.Entity.DbSet<AccountProfile> AccountProfile { get; set; }
}
AccountViewModels.cs > RegisterViewModel
public class RegisterViewModel
{
[Required]
[Display(Name = "Username")]
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; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
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; }
}
AccountController.cs
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationIdentityAccount
{
UserName = model.UserName,
Email = model.Email,
AccountProfile = new[] {new AccountProfile()
{
FirstName = model.FirstName,
LastName = model.LastName
}}
};
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking here");
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
I know that I should place FirstName and LastName inside:
var user = new ApplicationIdentityAccount
{
UserName = model.UserName,
Email = model.Email,
};
Since your question has two parts:
Your method for storing additional information is correct
You can't proceed unless you see the actual error, in order to see the details you need to add this where you create the user.
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException ex)
{
// Retrieve the error messages as a list of strings.
var errorMessages = ex.EntityValidationErrors
.SelectMany(x => x.ValidationErrors)
.Select(x => x.ErrorMessage);
// Join the list to a single string.
var fullErrorMessage = string.Join("; ", errorMessages);
// Combine the original exception message with the new one.
var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
// Throw a new DbEntityValidationException with the improved exception message.
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
}
I am making a mock social media app in Visual Studio 2013, using c#, asp.net-mvc5, and entity framework 6. I am trying to add custom user authentication
I have implemented the authentication in the web.config:
<authentication mode="Forms">
<forms loginUrl="~/AppUsers/Login" timeout="3000" />
</authentication>
and made sure that the ActionResult creates a cookie on login
[HttpPost]
public ActionResult Login(string userName, string password)
{
AppUser user = null;
if (db.AppUser.Any(m => m.UserName == userName)) {
user = db.AppUser.Where(m => m.UserName == userName).First();
if (user.Password == password) {
FormsAuthentication.SetAuthCookie(userName, true);
return RedirectToAction("AppUserProfile", new { id = user.Id });
}
}
return RedirectToAction("Login", new { message = "Invalid Password" });
}
But I am now stuck, whenever I try to check if HttpContext.User.Identity.IsAuthenticated, I get an error that says:
"An object reference is required for the non-static field, method, or property 'System.Web.HttpContext.User.get'"
Do I need to make my AppUser class extend an HttpContext class to make this error go away, or do I have to rewrite the whole class as it is?
public class AppUser
{
[Key]
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string UserName { 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; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string EmailAddress { get; set; }
public virtual ICollection<UserPost> UserPosts { get; set; }
}
Making
HttpContext.User.Identity.IsAuthenticated
into
HttpContext.Current.User.Identity.IsAuthenticated
fixed the issue for me
I have a class in my model in MVC:
public class NewModel
{
public bool AllComplexes { get; set; }
public int UserID { get; set; }
public int? RoleID { get; set; }
public int ComplexID { get; set; }
[Required(ErrorMessage = "Please enter a user name."), StringLength(50)]
public string Username { get; set; }
[Required(ErrorMessage = "Please enter Password"), StringLength(100, ErrorMessage = "Password cannot be longer than 100 characters")]
public string Password { get; set; }
[Compare("Password", ErrorMessage = "Passwords do not match")]
[Required(ErrorMessage = "Please confirm Password")]
public string RetypePassword { get; set; }
[RegularExpression( "^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*#[a-z0-9-]+(\\.[a-z0-9]+)*\\.([a-z]{2,4})$" , ErrorMessage = "Invalid email format." )]
[Required(ErrorMessage = "Please enter your e-mail address."), StringLength(50)]
public string Email { get; set; }
public List<NEWCategoryModel> Categories { get; set; }
//public List<NEWPrivilegeModel> userPrivList { get; set; }
public List<DropDownItem> ComplexList { get; set; }
public List<DropDownItem> RoleList { get; set; }
public string NewRole { get; set; }
public NewModel()
{
}
}
The Email address entered is stored in :
public string Email { get; set; }
I need to compare that Email address to all the email addresses stored in the database using Data Annotation. I assume I will need a Custom Data Annotation? But I have no idea how to do it.
This is an example of the query to get al the email addresses from the database:
db.ContactInformations.Where(x => x.EMail != null).Select(x => x.EMail);
public class NewModel
{
[EmailValidation(ErrorMessage = "The Email Address already exists")]
[RegularExpression( "^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*#[a-z0-9-]+(\\.[a-z0-9]+)*\\.([a-z]{2,4})$" , ErrorMessage = "Invalid email format." )]
[Required(ErrorMessage = "Please enter your e-mail address."), StringLength(50)]
public string Email { get; set; }
{
public class EmailValidation : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
PropmetEntities db = new PropmetEntities();
if (value != null)
{
var valueAsString = value.ToString();
IEnumerable<string> email = db.ContactInformations.Where(x => x.EMail != null).Select(x => x.EMail);
if (email.Contains(valueAsString))
{
var errorMessage = FormatErrorMessage(validationContext.DisplayName);
return new ValidationResult(errorMessage);
}
}
return ValidationResult.Success;
}
}
This can help you to create custom validation. Then, to check user is already exist in database by email, try:
bool exist = db.UserTable.Any(e => e.Email.ToLower() == emailValue.ToLower());
In this post you'll find a solution leveraging FluentValidation, which implements a custom DataAnnotation.
Your Unique Email Validation would look something along these lines:
[Validator(typeof(NewModelValidator))]
class NewModel
{
//...Model implementation omitted
}
public class NewModelValidator : AbstractValidator<NewModel>
{
public NewModelValidator()
{
RuleFor(x => x.Email).Must(IsUnieuqEmail).WithMessage("Email already exists");
}
private bool IsUniqueEmail(string mail)
{
var _db = new DataContext();
if (_db.NewModel.SingleOrDefault(x => x.Email == mail) == null) return true;
return false;
}
}