I have a Web API and I want my AutoHubUser to be used instead of the default one (IdentityUser). But I keep getting internal server error when I try to save it. What needs to be changed?
public class AutoHubUser : IdentityUser
{
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name = "Birth Date")]
public DateTime BirthDate { get; set; }
[Required]
public Gender Gender { get; set; }
public virtual ICollection<Auto> Autos { get; set; }
public virtual ICollection<UserMilestone> UserMilestones { get; set; }
public virtual ICollection<Friendship> Friendships { get; set; }
}
The account controller
// POST api/Account/Register
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityUser user = new AutoHubUser
{
UserName = model.UserName,
Email = model.Email,
BirthDate = model.BirthDate,
Gender = model.Gender
};
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
//IdentityResult result = await new UserManager<AutoHubUser>().CreateAsync(user, model.Password);
IHttpActionResult errorResult = GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
return Ok();
}
I also modified the RegisterBindingModel
public class RegisterBindingModel
{
[Required]
[Display(Name = "User name")]
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]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
[Required]
public Gender Gender { get; set; }
}
What else needs to be modified? It must be in the UserManager's CreateAsync method. But I haven't been able to find an example online. Thanks!
Related
I want Item2 to be mandatory only if Item.code = "yes". The InputModel is used in the Register at Register.cshtml.cs.
public class Item
{
[Required]
public string Id{ get; set; }
[Required]
public string desc{ get; set; }
[Required]
public string code{ get; set; }
}
public class Item2
{
[Required]
public string Id{ get; set; }
[Required]
public string slug{ get; set; }
}
public class InputModel
{
[Required]
public string Email { get; set; }
[Required]
public string Password{ get; set; }
[Required]
public Item Item { get; set; }
public Item2 Item2 { get; set; }
}
I intended to do something like this, IN InputModel
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Item.code=="yes")
{
===> set Item2 Required
}
}
This is the logic, can anyone help?
I'd suggest you to try FluentValidation, which was mentioned in the comments. It is really worth to take a bit of time to research it. Let's imagine you've downloaded it and want to implement your validation.
public class InputModel
{
public string Email { get; set; }
public string Password{ get; set; }
public Item Item { get; set; }
public Item2 Item2 { get; set; }
}
public class InputModelValidator
: AbstractValidator<InputModel>
{
public InputModelValidator()
{
RuleFor(request => request.Item2)
.NotNull()
.When(request =>
request.Item != null
&& !string.IsNullOrEmpty(request.Item.Code)
&& request.Item.Code == "yes")
.WithMessage("Item2 is mandatory if Item.code == 'yes'");
}
}
Still, there are many different ways of doing it, but I'm using FluentValidation in my project.
First, in the Item2 class, remove the [Required] attribute. Then, in the InputModel, you could implement the IValidatableObject, then Validate the values. Code as below:
public class Item
{
[Required]
public string Id { get; set; }
[Required]
public string desc { get; set; }
[Required]
public string code { get; set; }
}
public class Item2
{
public string Id { get; set; }
public string slug { get; set; }
}
public class InputModel: IValidatableObject
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} 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]
public Item Item { get; set; }
public Item2 Item2 { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Item.code.ToLower() == "yes")
{
if(Item2.Id==null)
yield return new ValidationResult($"Item2 ID is required!", new[] { "Item2.Id" });
if (Item2.slug == null)
yield return new ValidationResult($"Item2 slug is required!", new[] { "Item2.slug" });
}
}
}
The screenshot as below:
I have 2 Models. Organization and Site. A org can have many sites but a site can only have 1 org. I have been able to successfully create a page that you can create an org with its primary site and all saves fine into the database.
What id like to do is have a page that shows all the sites for an organization. Id like the url to be something like ~/Organizations/6/Sites. and to see info on a specific site, the url should read ~/organizations/6/sites/2
How would i go about achieving this? Can anyone point me in the right direction. My understanding is that it would be done within the endpoints.MapControllerRoute section under the startup.cs file.
Below are the 2 models and the view action for the org and the viewsites action for the sites which currently both reside in the orgcontroller
public class Organization:BaseEntity
{
[Required]
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "Logo")]
public string Logo { get; set; }
[Required]
[Display(Name = "Type")]
public OrganizationType Type { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedDate { get; set; }
public int Demo { get; set; }
[Required]
public bool Active { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
public virtual ICollection<Site> Sites { get; set; }
}
public class Site : BaseEntity
{
[Required]
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "Address")]
public string FullAddress
{
get
{
return StreetNumber + " " + StreetAddress + " " + Suburb + " " + State + " " + PostCode + " " + Country;
}
}
[Required]
[Display(Name = "Street Number")]
public string StreetNumber { get; set; }
[Required]
[Display(Name = "Street Address")]
public string StreetAddress { get; set; }
[Required]
[DataType(DataType.PostalCode)]
[Display(Name = "Postcode")]
public string PostCode { get; set; }
[Required]
[Display(Name = "Suburb")]
public string Suburb { get; set; }
[Required]
[Display(Name = "State")]
public string State { get; set; }
[Required]
[Display(Name = "Country")]
public string Country { get; set; }
[Required]
[DataType(DataType.PhoneNumber)]
[Display(Name = "Phone Number")]
public string PhoneNumber { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedDate { get; set; }
[Required]
public bool IsPrimary { get; set; }
public int Demo { get; set; }
[Required]
public bool Active { get; set; }
[Display(Name = "Image")]
public string Image { get; set; }
public virtual Organization Organization { get; set; }
}
// GET: Organizations/View/5
public async Task<IActionResult> View(Guid? id)
{
if (id == null)
{
return NotFound();
}
var organization = _context.Organizations.Include("Sites").Include("Contacts").FirstOrDefault(x=> x.ID == id);
ViewBag.SiteCount = organization.Sites.Count;
ViewBag.ContactCount = organization.Contacts.Count;
if (organization == null)
{
return NotFound();
}
return View(organization);
}
// GET: Organizations/View/5
public async Task<IActionResult> ViewSites(Guid? id)
{
if (id == null)
{
return NotFound();
}
List<Site> sites = _context.Organizations.Include("Sites").Where(x=>x.ID == id).ToList().FirstOrDefault().Sites.ToList();
return View(sites);
}
Here is a working demo like below:
Model:
public class BaseEntity
{
public Guid Id { get; set; }
}
public class Organization : BaseEntity
{
[Required]
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "Logo")]
public string Logo { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedDate { get; set; }
public int Demo { get; set; }
[Required]
public bool Active { get; set; }
public virtual ICollection<Site> Sites { get; set; }
}
public class Site : BaseEntity
{
[Required]
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "Address")]
public string FullAddress
{
get
{
return StreetNumber + " " + StreetAddress + " " + Suburb + " " + State + " " + PostCode + " " + Country;
}
}
[Required]
[Display(Name = "Street Number")]
public string StreetNumber { get; set; }
[Required]
[Display(Name = "Street Address")]
public string StreetAddress { get; set; }
[Required]
[DataType(DataType.PostalCode)]
[Display(Name = "Postcode")]
public string PostCode { get; set; }
[Required]
[Display(Name = "Suburb")]
public string Suburb { get; set; }
[Required]
[Display(Name = "State")]
public string State { get; set; }
[Required]
[Display(Name = "Country")]
public string Country { get; set; }
[Required]
[DataType(DataType.PhoneNumber)]
[Display(Name = "Phone Number")]
public string PhoneNumber { get; set; }
[DataType(DataType.DateTime)]
public DateTime CreatedDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime ModifiedDate { get; set; }
[Required]
public bool IsPrimary { get; set; }
public int Demo { get; set; }
[Required]
public bool Active { get; set; }
[Display(Name = "Image")]
public string Image { get; set; }
public virtual Organization Organization { get; set; }
}
Controller:
public class OrganizationsController : Controller
{
private readonly YourDbContext _context;
public OrganizationsController(YourDbContext context)
{
_context = context;
}
// GET: Organizations/Details/5
public async Task<IActionResult> Details(Guid? id,Guid siteId )
{
if (id == null)
{
return NotFound();
}
var organization = await _context.Organization.Include(o=>o.Sites)
.FirstOrDefaultAsync(m => m.Id == id);
var site = organization.Sites.Where(x => x.Id == siteId).FirstOrDefault();
return View(site);
}
}
Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//...
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}/{siteId?}");
});
}
Result:
Request url: https://localhost:portNumber/Organizations/Details/orgnizationid/siteid.
UPDATE:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "custom",
pattern: "Organizations/{id?}/{sites}/{siteId?}",
defaults: new { controller = "Organizations", action = "Details" });
});
Or a simple way is to use route attribute:
[Route("[controller]/{id}/sites/{siteId}")]
public async Task<IActionResult> Details(Guid id,Guid? siteId )
The way ive done it in the end is
Controller
// GET: Organizations/5
// GET: Organizations
[Route("[controller]/{id?}")]
public async Task<IActionResult> View(int? id)
{
if (id == 0)
{
return NotFound();
}
if (id == null)
{
return View("ViewAll",await _context.Organizations.Include("Sites").Include("Contacts").ToListAsync());
}
var organization = _context.Organizations.Include("Sites").Include("Contacts").FirstOrDefault(x=> x.ID == id);
if (organization == null)
{
return NotFound();
}
return View("View",organization);
}
// GET: Organizations/5/Sites/2
// GET: Organizations/5/Sites
// GET: Organizations/5
[Route("[controller]/{id}/sites/{siteId?}")]
public async Task<IActionResult> ViewSites(int ordId, int? siteId)
{
if (ordId == 0)
{
return NotFound();
}
if (siteId == 0)
{
List<Site> sites = _context.Organizations.Include("Sites").Where(x => x.ID == ordId).ToList().FirstOrDefault().Sites.ToList();
return View("ViewSites",sites);
}
Site site = _context.Organizations.Include("Sites").Where(x => x.ID == ordId).ToList().FirstOrDefault().Sites.ToList().Where(y=>y.ID == siteId).FirstOrDefault();
return View("ViewSite", site);
}
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "OrgSites",
pattern: "Organizations/{id}/{sites}/{siteId?}",
defaults: new { controller = "Organizations", action = "ViewSites" });
endpoints.MapControllerRoute(
name: "Orgs",
pattern: "Organizations/{id?}",
defaults: new { controller = "Organizations", action = "View" });
endpoints.MapControllerRoute(
name: "Orgs",
pattern: "Organizations",
defaults: new { controller = "Organizations", action = "View" });
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
I have two classes - parent and child.
This is the parent class
[Table("tbl_Parent")]
public partial class Parent
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
[ScaffoldColumn(false)]
public int Parent_Id { get; set; }
[Required(ErrorMessage = "you must provide parent First Name")]
[Display(Name = "Full Name")]
public string Parent_Full_Name{ get; set; }
[Required(ErrorMessage = "you must provide parent Email Address")]
[Display(Name = "Email Address")]
[DataType(DataType.EmailAddress)]
[EmailAddress(ErrorMessage = "Correct Input")]
[StringLength(100, ErrorMessage = "at least 10 Char", MinimumLength = 10)]
public string Parent_Email { get; set; }
[Required(ErrorMessage = "you must provide parent phone number")]
[Display(Name = "Phone Number")]
[DataType(DataType.PhoneNumber)]
public int Parent_Phone { get; set; }
[Required(ErrorMessage = "you must provide parent password")]
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Parent_Password { get; set; }
public string Parent_Location { get; set; }
[Required(ErrorMessage = "you must provide parent status")]
[Display(Name = "Parent status")]
public string Parent_status { get; set; }
public string Par_User_Type { get; set; }
public ICollection<Child> child { get; set; }
}
and this is the child class
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Chi_Id { get; set; }
[Required(ErrorMessage ="you must provide child first name")]
[Display(Name ="Child First Name")]
public string Chi_First_Name { get; set; }
[Required(ErrorMessage ="you must provide child last Name")]
[Display(Name ="Child Last Name")]
public string Chi_Last_Name { get; set; }
[Required(ErrorMessage ="you must provide child age")]
[Display(Name ="Child Age")]
[Range(0,18, ErrorMessage = "Correct Input")]
public int Age { get; set; }
[Required(ErrorMessage ="you must provide child gender")]
[Display(Name ="Child Gender")]
public string Gender { get; set; }
[Display(Name ="Child School")]
public string Chi_School { get; set; }
[Required(ErrorMessage ="you must provide parent status")]
[Display(Name ="Child Parent Status")]
public string Chi_parent_status { get; set; }
[Display(Name ="Child Image Path")]
public string Chi_Image_Path { get; set; }
public virtual Admin admin { get; set; }
public int Adm_ID { get; set; }
public virtual Parent parent { get; set; }
public int Par_ID { get; set; }
}
The parent class can have many children.
I want add id of child in parent class across controller. This is my controller:
[HttpGet]
public ActionResult Rigester()
{
if (Session["ID"] == null)
{
return RedirectToAction("Login", "Home");
}
return View();
}
[HttpPost]
public ActionResult Rigester(Parent parent,int id)
{
if (ModelState.IsValid)
{
using (Context db = new Context())
{
var child1 = db.child.Where(x => x.Chi_Id == id).First();
parent.Par_User_Type = "Parent";
parent.child.Add(child1);
db.parent.Add(parent);
db.SaveChanges();
return RedirectToAction("Home", "Admin");
}
}
return View();
}
In the controller, I get an error when executing this code:
Null reference exception
on this line of code:
parent.child.Add(child1);
The end of each class has relationship between another class.
How can I add child when register new parent?
Instead of adding via navigation properties, in your controller you could assign the ParentId as foreign key for the child.
In the code below, first we added parent to the database, then we assigned the parentId in the child object.
[HttpPost]
public ActionResult Rigester(Parent parent,int id)
{
if (ModelState.IsValid)
{
using (Context db = new Context())
{
parent.Par_User_Type = "Parent";
db.parent.Add(parent);
db.SaveChanges();
var child1 = db.child.Where(x => x.Chi_Id == id).First();
child1.Par_Id = parent.Parent_Id;
db.SaveChanges();
return RedirectToAction("Home", "Admin");
}
}
return View();
}
Currently I create a shop and I use ASP Identity razor pages to login, logout and registration. I have default IdentityUser. I have also ASPNetUsers table and I want reference row UserId to my other table Orders. My main purpose to achieve is when user logg in, he can check his completed orders from database. I know how to use LINQ to get order from database, but I didn't know how to connect that with Identity. I also use Session for adding item to cart if it is important.
public class AppDbContext : IdentityDbContext<IdentityUser>
{
public AppDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<Game> Games { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<SubGenre> SubGenres { get; set; }
public DbSet<CartItem> CartItems { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<ShipAddress> ShipAddresses { get; set; }
}
public class ShipAddress
{
[BindNever]
public int ShipAddressId { get; set; }
public List<Order> Orders { get; set; }
[Required(ErrorMessage = "Wpisz swoje imię!")]
[StringLength(50)]
[Display(Name = "Imię:")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Wpisz swoje nazwisko!")]
[StringLength(50)]
[Display(Name = "Nazwisko:")]
public string LastName { get; set; }
[Required(ErrorMessage = "Wpisz nazwę ulicy!")]
[StringLength(50)]
[Display(Name = "Ulica:")]
public string Address1 { get; set; }
[Required(ErrorMessage = "Wpisz numer domu/lokalu!")]
[StringLength(50)]
[Display(Name = "Nr domu/lokalu:")]
public string Address2 { get; set; }
[Required(ErrorMessage = "Wpisz kod pocztowy!")]
[StringLength(6)]
[Display(Name = "Kod pocztowy:")]
public string ZipCode { get; set; }
[Required(ErrorMessage = "Wpisz miejscowość!")]
[StringLength(50)]
[Display(Name = "Miejscowość:")]
public string City { get; set; }
[Required(ErrorMessage = "Wpisz numer kontaktowy!")]
[StringLength(9)]
[Display(Name = "Nr telefonu:")]
public string PhoneNumber { get; set; }
[BindNever]
public decimal OrderTotal { get; set; }
[BindNever]
public DateTime OrderPlaced { get; set; }
public IdentityUser User { get; set; }
public int IdentityUserId { get; set; }
}
Current Login User
var userID = User.Identity.GetUserId();
This will give your current login user id then you can apply linq for based on this id with and condition of completed order you store in table
Use User's Identity which u logged in by using
string userID = User.Identity.GetUserId();
Successfully I added some fields in AspNetUsers table but I don't know how I can retrieve them. My project is asp.net web api and I can retrieve username from token. I want to return departmentId by given userId, or username.
and trying like but this gives me null exeption
private ApplicationUserManager _userManager;
public int GetdeptId(string username)
{
var dept = _userManager.Users.Where(d => d.UserName == username).Select(c => c.DepartmentId).FirstOrDefault();
return dept;
}
Here is the way I could create fields in my AspNetUsers and I can insert values successfully. The problem is to return values from AspNetUsers.
public class RegisterBindingModel
{
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[Display(Name = "FirstName")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Lastname")]
public string Lastname { get; set; }
[Required]
[Display(Name = "Department")]
public int DepartmentId { 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; }
}
And then the registerration
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email, Firstname = model.FirstName, LastName = model.Lastname, DepartmentId = model.DepartmentId };
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
Thank you in advance!
Try!
var context = new IdentityDbContext();
var users = context.Users.ToList();
If you have access to your ApplicationDbContext as say, _db, then you can cast it to IdentityDbContext and access the tables through that. e.g.
IdentityDbContext context = _db as IdentityDbContext;
IEnumerable<User> users = context.Users;