How to display the name of the reference in my table AspNetUsers - asp.net-mvc

I am wanting to display the name of the city which I have referenced in my table but I can not AspNetUser how.
This is the IndexViewModels:
public class IndexViewModel {
public bool HasPassword { get; set; }
public IList<UserLoginInfo> Logins { get; set; }
public string PhoneNumber { get; set; }
public bool TwoFactor { get; set; }
public bool BrowserRemembered { get; set; }
public string Nombre { get; set; }
public string Apellido { get; set; }
public string Direccion { get; set; }
public string Pais { get; set; }
public int LocalidadID { get; set; }
public string CodigoPostal { get; set; }
public string Telefono { get; set; }
public virtual Localidad Localidad { get; set; }
}
This is IdentityModels of class ApplicationUser.:
public class ApplicationUser : IdentityUser {
public int LocalidadID { get; set; }
public string Nombre { get; set; }
public string Apellido { get; set; }
public string Direccion { get; set; }
public string Pais { get; set; }
public string CodigoPostal { get; set; }
public string Telefono { get; set; }
public System.DateTime FechaRegistro { get; set; }
// FOREIGN KEY
public virtual Localidad Localidad { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) {
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
This is the controller Index
public async Task<ActionResult> Index(ManageMessageId? message)
{
if (User.Identity.Name.Equals("guest#guest.com"))
return RedirectToAction("GuestIndex");
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var store = new UserStore<ApplicationUser>(new ApplicationDbContext());
var ctx = store.Context;
var usuario = manager.FindById(User.Identity.GetUserId());
ApplicationDbContext db = new ApplicationDbContext();
var model = new IndexViewModel
{
HasPassword = HasPassword(),
PhoneNumber = await UserManager.GetPhoneNumberAsync(User.Identity.GetUserId()),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(User.Identity.GetUserId()),
Logins = await UserManager.GetLoginsAsync(User.Identity.GetUserId()),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(User.Identity.GetUserId()),
Direccion = usuario.Direccion,
Nombre = usuario.Nombre,
Apellido = usuario.Apellido,
Telefono = usuario.Telefono,
LocalidadID = usuario.LocalidadID,
//Localidades = db.Localidades.Where(l => l.LocalidadID==usuario.LocalidadID).Select(l => new {Nombre = l.Nombre}),
CodigoPostal = usuario.CodigoPostal
};
return View(model);
}
And my View i throw me error:
<p>Argentina, #Model.Localidad.Departamento.Provincia.Nombre</p>
Error: Object reference not set to an instance of an object.

The Solution was to add the following line:
Localidad = (from l in db.Localidades where l.LocalidadID == usuario.LocalidadID select l).First<Localidad>()
Leaving the function like this:
public async Task<ActionResult> Index(ManageMessageId? message)
{
if (User.Identity.Name.Equals("guest#guest.com"))
return RedirectToAction("GuestIndex");
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var store = new UserStore<ApplicationUser>(new ApplicationDbContext());
var ctx = store.Context;
var usuario = manager.FindById(User.Identity.GetUserId());
ApplicationDbContext db = new ApplicationDbContext();
var model = new IndexViewModel
{
HasPassword = HasPassword(),
PhoneNumber = await UserManager.GetPhoneNumberAsync(User.Identity.GetUserId()),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(User.Identity.GetUserId()),
Logins = await UserManager.GetLoginsAsync(User.Identity.GetUserId()),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(User.Identity.GetUserId()),
Direccion = usuario.Direccion,
Nombre = usuario.Nombre,
Apellido = usuario.Apellido,
Telefono = usuario.Telefono,
LocalidadID = usuario.LocalidadID,
Localidad = (from l in db.Localidades where l.LocalidadID == usuario.LocalidadID select l).First<Localidad>(),
CodigoPostal = usuario.CodigoPostal
};
return View(model);
}

The Departamento.Provincia of the Localidad won't be loaded, and maybe the Localidad itself.
You have to load it from the context by using Include or load it explicitly in another query
ex:
LocalidadID = db.Localidads.Include("Departamento.Provincia.").Where(a=>a.LocalidadId == usuario .LocalidadID)

Related

Automapper map Dictionary<string, string> and List<string> properties to view model

I have the following view model
public class PlanDetail
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
[DisplayFormat(DataFormatString = "{0:$#.##}")]
public decimal Price { get; set; }
public string FrequencyAbbreviatedName { get; set; }
[Display(Name = "Frequency")]
public string FrequencyName { get; set; }
[Display(Name = "Events")]
public int EventLimit { get; set; }
[Display(Name = "Help Center Access")]
public bool HelpCenterAccess { get; set; }
[Display(Name = "Email Support")]
public bool EmailSupport { get; set; }
[Display(Name = "Priority Email Support")]
public bool PriorityEmailSupport { get; set; }
[Display(Name = "Phone Support")]
public bool PhoneSupport { get; set; }
public bool Active { get; set; }
public string PictureUrl { get; set; }
public bool BestValue { get; set; }
}
I am using stripe.com products and prices.
In my mapping profile class, I am able to map to the basic properties (eg Id, Name, Description, Active).
Mapper.Map<Product,PlanDetail>();
I am not sure how to map the Metadata property (Dictionary<string,string>) or the Images property (List <string>) in the stripe product object to some of the PlanDetail properties.
I created the stripe products in my seed class, and added values to the Metadata and Image properties.
public static async Task SeedStripeAsync(string stripeKey)
{
StripeConfiguration.ApiKey = stripeKey;
var productService = new ProductService();
var priceService = new PriceService();
var products = await productService.ListAsync();
var productsData = System.IO.File.ReadAllText("../Infrastructure/Data/SeedData/stripe_products.json");
var productPlans = JsonSerializer.Deserialize<List<StripeProductSeed>>(productsData);
foreach (var item in productPlans)
{
if (!products.Any(x=> x.Name.Equals(item.Name, StringComparison.InvariantCultureIgnoreCase)))
{
var productOptions = new ProductCreateOptions
{
Name = item.Name,
Description = item.Description,
Active = item.Active,
Images = new List<string>(),
Metadata = new Dictionary<string, string>()
};
productOptions.Images.Add(item.PictureUrl);
productOptions.Metadata.Add("EventLimit", item.EventLimit.ToString());
productOptions.Metadata.Add("HelpCenterAccess", item.HelpCenterAccess.ToString());
productOptions.Metadata.Add("EmailSupport", item.EmailSupport.ToString());
productOptions.Metadata.Add("PriorityEmailSupport", item.PriorityEmailSupport.ToString());
productOptions.Metadata.Add("PhoneSupport", item.PhoneSupport.ToString());
productOptions.Metadata.Add("BestValue", item.BestValue.ToString());
var newProduct = await productService.CreateAsync(productOptions);
var priceOptions = new PriceCreateOptions
{
UnitAmountDecimal = item.Price,
Currency = "usd",
Recurring = new PriceRecurringOptions()
{
Interval = item.Interval,
IntervalCount = (long)item.IntervalCount
},
Product = newProduct.Id
};
await priceService.CreateAsync(priceOptions);
}
}
}
I would like to map the stripe Product Metadata properties such as EventLimit, HelpCenterAccess, EmailSupport, PriorityEmailSupport, PhoneSupport, and BestValue to their respective counterparts in the PlanDetail view model.
In addition, I would like to map the stripe Product Image property to the PictureUrl property in the PlanDetail view model.
Any ideas or suggestions how to use automapper for theses properties would be much appreciated.
Here's what I assume
// Just demo class
public class StripeProductSeed
{
public string PictureUrl { get; set; }
public int EventLimit { get; set; }
public bool HelpCenterAccess { get; set; }
public bool EmailSupport { get; set; }
public bool PriorityEmailSupport { get; set; }
public bool PhoneSupport { get; set; }
public bool BestValue { get; set; }
public List<string> ExtractImages() => new() { PictureUrl };
public Dictionary<string, string> ExtractMetaData() => new()
{
{nameof(EventLimit), EventLimit.ToString()},
{nameof(HelpCenterAccess), HelpCenterAccess.ToString()},
{nameof(EmailSupport), EmailSupport.ToString()},
{nameof(PriorityEmailSupport), PriorityEmailSupport.ToString()},
{nameof(PhoneSupport), PhoneSupport.ToString()},
{nameof(BestValue), BestValue.ToString()}
};
}
The map should be:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<StripeProductSeed, PlanDetail>()
.ForMember(dst => dst.Images, x => x.MapFrom(src => src.ExtractImages()))
.ForMember(dst => dst.Metadata, x => x.MapFrom(src => src.ExtractMetaData()));
}
}

MVC register method broken

I am working on a basic MVC project, pretty much out of the box with minor enhancements. I have therefore customized the user properties a bit, but not too much... however, it seems not to be working anymore since then. I've done the exact same before without running into errors. Any ideas where I went wrong??
IdentityModels:
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit https://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
//public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public string DateOfBirth { get; set; }
//public string Email { get; set; }
public string PhoneNumberPrefix { get; set; }
public string PhoneNumberSuffix { get; set; }
//public string PhoneNumber { get; set; }
public bool PhoneNumberVerified { get; set; }
public string BillingAddress { get; set; }
public bool BillingAddressIsShippingAddress { get; set; }
public string ShippingAddress { get; set; }
public string VATNumber { get; set; }
public string PreferredLanguage { get; set; }
public DateTime RegisteredDateTime { get; set; }
public string RegisteredLatitude { get; set; }
public string RegisteredLongitude { get; set; }
public string RegisteredLocation { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class UserDbContext : IdentityDbContext<ApplicationUser>
{
public UserDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static UserDbContext Create()
{
return new UserDbContext();
}
}
AccountController:
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
// define variables
var userID = User.Identity.GetUserId();
DateTime nowUTC = DateTime.Now.ToUniversalTime();
DateTime nowLocal = DateTime.Now.ToLocalTime();
// check model state and submit form
if (ModelState.IsValid)
{
var user = new ApplicationUser
{
UserName = model.UserName,
FirstName = model.FirstName,
LastName = model.LastName,
Gender = model.Gender,
DateOfBirth = model.DateOfBirth,
Email = model.Email,
PhoneNumberPrefix = model.PhoneNumberPrefix,
PhoneNumberSuffix = model.PhoneNumberSuffix,
PhoneNumber = model.PhoneNumberPrefix + model.PhoneNumberSuffix,
BillingAddress = model.BillingAddress,
VATNumber = "MwSt-Nummer",
PreferredLanguage = model.PreferredLanguage,
RegisteredDateTime = nowUTC,
RegisteredLatitude = model.RegisteredLatitude,
RegisteredLongitude = model.RegisteredLongitude,
RegisteredLocation = model.RegisteredLocation
};
// send confirmation email
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
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, "Bestätige Dein Konto", "Bitte bestätige Dein Konto indem Du hier klickst.");
ViewBag.Message = "Fast geschafft! Du hast eine Email mit weiteApplicationDbContextren Instruktionen erhalten um die Anmeldung abzuschliessen.";
// track user activity: post method includes activity name and timestamp along with location
var SUCCESS = new UserActivities
{
UserID = userID,
ActivityName = "Register_Success",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = model.RegisteredLatitude,
ActivityLongitude = model.RegisteredLongitude,
ActivityLocation = model.RegisteredLocation
};
DATADB.UserActivityList.Add(SUCCESS);
DATADB.SaveChanges();
return View("PostRegistration");
}
AddErrors(result);
}
var FAILURE = new UserActivities
{
UserID = userID,
ActivityName = "Register_Failure",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = model.RegisteredLatitude,
ActivityLongitude = model.RegisteredLongitude,
ActivityLocation = model.RegisteredLocation
};
DATADB.UserActivityList.Add(FAILURE);
DATADB.SaveChanges();
// repopulate dropdownlists
ViewBag.gender = DATADB.GenderList.Select(m => new SelectListItem()
{
Text = m.Gender,
Value = m.Gender
}).ToList();
ViewBag.countryCode = DATADB.CountryCodeList.Select(m => new SelectListItem()
{
Text = m.CountryCode,
Value = m.CountryCode
}).ToList();
ViewBag.preferredLanguage = DATADB.LanguageList.Select(m => new SelectListItem()
{
Text = m.Language,
Value = m.Language
}).ToList();
return View(model);
}

Cannot insert the value NULL into column from unrelated entity

I'm getting a "Cannot insert null into column" error from an unrelated table when trying to add a new record for the "original" table.
I have the following two (relevant) entities:
public class Complex
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public Guid OwnerId { get; set; }
[ForeignKey("OwnerId")]
public Owner Owner { get; set; }
public Guid AddressId { get; set; }
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
public virtual ICollection<Unit> Units { get; set; }
public virtual ICollection<StaffMember> StaffMembers { get; set; }
public Complex()
{
this.Id = System.Guid.NewGuid();
this.Units = new HashSet<Unit>();
this.StaffMembers = new HashSet<StaffMember>();
}
public void AddUnit(Unit unit)
{
Units.Add(unit);
}
public void AddStaff(StaffMember staffMember)
{
StaffMembers.Add(staffMember);
}
}
and
public class Owner
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public Guid ContactInfoId { get; set; }
[ForeignKey("ContactInfoId")]
public ContactInfo ContactInfo { get; set; }
public ICollection<StaffMember> Employees { get; set; }
public ICollection<Complex> Complexes { get; set; }
public Owner()
{
this.Id = System.Guid.NewGuid();
this.Employees = new HashSet<StaffMember>();
this.Complexes = new HashSet<Complex>();
}
public void AddEmployee(StaffMember employee)
{
Employees.Add(employee);
}
public void AddComplex(Complex complex)
{
Complexes.Add(complex);
}
}
I'm trying to add a new owner in the following code:
if (ModelState.IsValid)
{
Owner newOwner = new Owner();
ContactInfo newContactInfo = new ContactInfo();
Address newAddress = new Address();
newAddress.Address1 = viewModel.ContactInfo.Address.Address1;
newAddress.Address2 = viewModel.ContactInfo.Address.Address2;
newAddress.City = viewModel.ContactInfo.Address.City;
newAddress.State = viewModel.ContactInfo.Address.State;
newAddress.Zip = viewModel.ContactInfo.Address.Zip;
newContactInfo.Address = newAddress;
newContactInfo.Email = viewModel.ContactInfo.Email;
newContactInfo.Phone1 = viewModel.ContactInfo.Phone1;
newContactInfo.Phone2 = viewModel.ContactInfo.Phone2;
newOwner.Name = viewModel.Name;
newOwner.ContactInfo = newContactInfo;
using (REMSDAL dal = new REMSDAL())
{
dal.Owners.Add(newOwner);
var result = await dal.SaveChangesAsync();
if (result > 0)
{
viewModel.ActionStatusMessageViewModel.StatusMessage = "Owner " + viewModel.Name + " added.";
viewModel.Name = "";
return View(viewModel);
}
}
}
...but getting this error:
Exception Details: System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'OwnerId', table 'REMS.dbo.Complexes'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
How can I be getting an error regarding Complexes when I'm trying to add an Owner?

Exception in SaveChanges() method (Entity.Framework)

There is class User
namespace TaskManager.Models
{
public class User
{
private const int NAME_LENGTH = 200;
private const int EMAIL_LENGTH = 100;
private const int PASSWORD_MIN_LENGTH = 5;
private const int PASSWORD_MAX_LENGTH = 20;
public int Id { get; set; }
[Required]
[StringLength(NAME_LENGTH)]
public string Name { get; set; }
[Required]
[EmailAddress]
[StringLength(EMAIL_LENGTH)]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[StringLength(PASSWORD_MAX_LENGTH, MinimumLength = PASSWORD_MIN_LENGTH)]
public string Password { get; set; }
public string PasswordSalt { get; set; }
[Required]
[DefaultValue(UserType.User)]
public UserType Type { get; set; }
public ICollection<Task> Tasks { get; set; }
}
public enum UserType
{
Admin = 0,
User = 1
}
}
and I try to create custom user registration using SimpleCrypto.
Here is my method
[HttpGet]
public ActionResult Registration()
{
return View();
}
[HttpPost]
public ActionResult Registration(User user)
{
if (ModelState.IsValid)
{
if (!IsUserExist(user.Email))
{
var crypto = new SimpleCrypto.PBKDF2();
var encrpPass = crypto.Compute(user.Password);
var newUser = _db.Users.Create();
newUser.Name = user.Name;
newUser.Email = user.Email;
newUser.Type = UserType.User.ToString();
newUser.Password = encrpPass;
newUser.PasswordSalt = crypto.Salt;
_db.Users.Add(newUser);
_db.SaveChanges();
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "User already exists");
}
}
else
{
ModelState.AddModelError("", "Data is incorrect");
}
return View(user);
}
If I use this table schema, registration works correctly
but if I try to set Id as Primary Key and set Identity == true and Identity Increment = 1
I got an Exception in _db.SaveChanges(); method.
What do I do wrong? How to fix it?
Exception
System.Data.SqlServerCe.SqlCeException: The column cannot be modified. [ Column name = Id ]
I tried to change model
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
but I got the same exception.

Code First Many to Many : how to add a collection to an object

I have a Many to Many relationship between User and Role. They are set up as follows :
public partial class User
{
//public User()
//{
// //this.DateCreated = DateTime.Now; //set default value
// Roles = new HashSet<Role>();
//}
public ICollection<Role> Roles { get; set; } //many to many relationship
public int UserId { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string City { get; set; }
//foreign key
public int CountryId { get; set; }
//navigation properties
public virtual Country Country { get; set; }
//foreign key
public int LanguageId { get; set; }
//navigation properties
public virtual Language Language { get; set; }
public string EmailAddress { get; set; }
public long? FacebookId { get; set; }
public DateTime DateCreated { get; set; }
}
public partial class Role
{
//public Role()
//{
// Users = new HashSet<User>();
//}
public ICollection<User> Users { get; set; } //many to many relationship
public int RoleId { get; set; }
public string RoleName { get; set; }
}
//many to many relationship
modelBuilder.Entity<User>().
HasMany(c => c.Roles).
WithMany(p => p.Users).
Map(
m =>
{
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
m.ToTable("UserRoles", schemaName: "Main");
});
In my code where I add a new user, I want to be able to add Roles to that user. But whenever I do this, new Roles are also added to the Roles table. What is the correct way to do this?
[HttpPost]
public ActionResult UserAdd(UserDTO user)
{
if (ModelState.IsValid)
{
//do mapping manually here
Country country = _repository.GetCountryByCountryId(user.CountryId);
Language language = _repository.GetLanguageByLanguageId(user.LanguageId);
User entity = new User();
entity.FirstName = user.FirstName;
entity.Surname = user.Surname;
entity.Username = user.Username;
entity.Password = user.Password;
entity.City = user.City;
entity.CountryId = country.CountryId;
entity.LanguageId = language.LanguageId;
entity.Country = country;
entity.Language = language;
entity.EmailAddress = user.EmailAddress;
entity.FacebookId = null;
entity.DateCreated = DateTime.Now;
entity.Roles = new List<Role>();
foreach (int i in user.Roles)
{
Role role = _repository.GetRoleByRoleId(i);
entity.Roles.Add(new Role { RoleId = i, RoleName = role.RoleName });
}
int newUserId = _repository.AddUser(entity);
return View();
} }
entity.Roles.Add(new Role { RoleId = i, RoleName = role.RoleName });
Here is the problem, because you create new instance, it means absolutely new role. You have to work with role from your context:
foreach (int i in user.Roles)
{
Role role = _repository.GetRoleByRoleId(i);
entity.Roles.Add(role); // don't create new instance here!
}

Resources