Register one to many relationship in ASP.NET MVC - asp.net

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();
}

Related

How to require the filling of an Entity attribute dependent on a condition - ASP NET Core MVC and Entity Framework

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:

How to check completed orders when user is logged in?

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();

Dropdownlistfor Object reference not set to an instance of an object after the ModelState.IsValid

Having problem with DropdownListFor when it passes the (ModelState.IsValid). when it passes the DropdownList, the error (Object reference not set to an instance of an object.) occurs
VIEW
Error in this line of the view
#Html.DropDownListFor(model => model.si_g_code, new= SelectList(Model.Guardian,"g_ref_code","fullname"), "Select Guardian")
#Html.ValidationMessageFor(model => model.si_g_code)
#Html.DropDownListFor(model => model.si_gl_id, new SelectList(Model.GradeLevel,"gl_id","gl_name"), "Select Grade Level", new { id = "ddlGrade" })
#Html.ValidationMessageFor(model => model.si_gl_id)
Controller
[HttpGet]
public ActionResult RegisterStudent()
{
Models.ModelActions action = new Models.ModelActions();
var model = new acgs_qm.Models.CreateStudent
{
GradeLevel = action.getGrade(),
Guardian = action.getGuardian(),
si_id = action.getStudentNum()
};
return View(model);
}
[HttpPost]
public ActionResult RegisterStudent(CreateStudent Create)
{
acgs_qm.Models.ModelActions Ma = new acgs_qm.Models.ModelActions();
if (ModelState.IsValid)
{
Ma.insertStudent(Create);
}
return View();
}
Model
public class CreateStudent
{
[DisplayAttribute(Name = "Student ID")]
public string si_id { get; set; }
[Required]
[DisplayAttribute(Name = "First Name")]
public string si_fname { get; set; }
[Required]
[DisplayAttribute(Name = "Middle Name")]
public string si_mname { get; set; }
[Required]
[DisplayAttribute(Name = "Last Name")]
public string si_lname { get; set; }
[DataType(DataType.Text)]
[Required]
[DisplayAttribute(Name = "Contact Number")]
public string si_contact_no { get; set; }
[Required]
[DisplayAttribute(Name = "Gender")]
public string si_gender { get; set; }
[Required]
[DisplayAttribute(Name = "Civil Status")]
public string si_civil_status { get; set; }
[Required]
[DisplayAttribute(Name = "Birthdate")]
public string si_birthdate { get; set; }
[Required]
[DisplayAttribute(Name = "Birth Place")]
public string si_brith_place { get; set; }
[Required]
[DisplayAttribute(Name = "Guardian")]
public string si_g_code { get; set; }
[Required]
[DisplayAttribute(Name = "Enrolled")]
public string si_enrolled { get; set; }
[Required]
[DisplayAttribute(Name = "Email")]
public string si_email { get; set; }
[Required]
[DisplayAttribute(Name = "Grade Level")]
public int si_gl_id { get; set; } //fk
[Required]
[DisplayAttribute(Name = "Section")]
public int si_sec_id { get; set; } //fk
public IEnumerable<GradeLevel> GradeLevel { get; set; }
public IEnumerable<Guardian> Guardian { get; set; }
}
public class GradeLevel
{
public string gl_id { get; set; }
public string gl_roman_no { get; set; }
public string gl_name { get; set; }
}
public class Guardian
{
public string g_ref_code { get; set; }
public string g_fname { get; set; }
public string g_mname { get; set; }
public string g_lname { get; set; }
public string g_contact { get; set; }
public string fullName { get; set; }
}
Help is much appreciated :)
The problem is here:
#Html.DropDownListFor(model => model.si_gl_id, new SelectList(Model.GradeLevel,"gl_id","gl_name"), "Select Grade Level", new { id = "ddlGrade" })
The SelectList takes Model.GradeLevel as parameter which is null
So you have to change the code like this.
[HttpPost]
public ActionResult RegisterStudent(CreateStudent Create)
{
acgs_qm.Models.ModelActions Ma = new acgs_qm.Models.ModelActions();
if (ModelState.IsValid)
{
Ma.insertStudent(Create);
}
//Populate the values so that they wont be null in selectlist
Create.GradeLevel = action.getGrade();
Create.Guardian = action.getGuardian();
return View(Create);
}
Since in your view if dropdownlist is not selected then the model field will be null. So while passing to view in post method explicitly assign these values because always the dropdownlist needs the value.
Only if the model is passed to view,the object reference is set. Here in this code, when you are passing the Create to the view the reference of the model object is set to the instance of the Create object.
This works for sure I checked. Wherever there is Selectlist you have to make sure the value passed is not null. For that purpose only i am populating
GradeLevel and Guardian
Http is stateless. That means it will not keep your data between your 2 requests.
In your GET action method, you are loading data for the dropdowns and sending to the view. But in your HttpPost action method, When ModelState.IsValid is false, you are returning the same view. But you are not passing any model/viewmodel to that which has data for your dropdowns. Your razor view is trying to use the GradeLevel and Guardian collection to render the dropdown ,but since we did not load the data for those properties, it is NULL. That is the reason you are getting this error.
What you should do is, before returning the view, reload the GradeLevel and Guardian property values again.
[HttpPost]
public ActionResult RegisterStudent(CreateStudent Create)
{
var Ma = new acgs_qm.Models.ModelActions();
if (ModelState.IsValid)
{
Ma.insertStudent(Create);
}
//Reload the data
Create.GradeLevel = action.getGrade(),
Create.Guardian = action.getGuardian(),
return View(Create);
}

Subclassing IdentityUser ASP.NET

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!

DropDown box in ASP .Net MVC 3 Razor Entity Framework

i am new to ASP .NET and Particularly in ASP .Net MVC3 Razor...
i have created view for Clients and Executives in MVC3 Razor.
What i did is 1st i created Model called Clients.cs
namespace MVCInetClient.Model
{
[Table("tbl_Customer")]
public class Clients
{
[Required,Key,DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Client ID")]
public int ClientId { get; set; }
[Required]
[Display(Name = "Client Name")]
public string ClientName { get; set; }
[Required]
[Display(Name = "Executive Name")]
public string ExecutiveName { get; set; }
[Required]
[Display(Name = "Contact Name")]
public string ContactPerson { get; set; }
[Display(Name = "Address")]
public string Add1 { get; set; }
[Display(Name = " ")]
public string Add2 { get; set; }
[Display(Name = " ")]
public string Add3 { get; set; }
[Display(Name = "Pincode")]
public string Pin { get; set; }
[Display(Name = "State")]
public string State { get; set; }
[Display(Name = "Country")]
public string Country { get; set; }
[Display(Name = "Phone")]
public string Phone { get; set; }
[Required]
[StringLength(10)]
[RegularExpression("\\d+")]
[Display(Name = "Mobile")]
public string Mobile { get; set; }
[Display(Name = "Fax")]
public string Fax { get; set; }
[Display(Name = "Email")]
public string Email { get; set; }
[Display(Name = "Website")]
public string Web { get; set; }
}
public class ClientsDbContext : DbContext
{
public DbSet<Clients> Clients { get; set; }
public DbSet<Executives> Executives{ get; set; }
}
}
After that i Created the Controller called ClientsController with Scaffolding Options,
Template : Controller With Read/Write actions and Views, using Entity Framework
Model Class : Clients (MVCInetClient.Models)
Data Context Class : ClientsDbContext (MVCInetClient.Models)
It Created View Create, Edit, Index, Delete Automatically and its working Fine too.
Similarly i did for model called Executives.cs
namespace MVCInetClient.Models
{
[Table("tbl_Executive")]
public class Executives
{
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Executive ID")]
public int ExecutiveId { get; set; }
[Required]
[Display(Name = "Executive Name")]
public string ExecutiveName { get; set; }
[Display(Name = "Address")]
public string Add1 { get; set; }
[Display(Name = " ")]
public string Add2 { get; set; }
[Display(Name = " ")]
public string Add3 { get; set; }
[Display(Name = "Pincode")]
public string Pin { get; set; }
[Display(Name = "State")]
public string State { get; set; }
[Display(Name = "Country")]
public string Country { get; set; }
[Display(Name = "Phone")]
public string Phone { get; set; }
[Required]
[StringLength(10)]
[RegularExpression("\\d+")]
[Display(Name = "Mobile")]
public string Mobile { get; set; }
[Display(Name = "Email")]
public string Email { get; set; }
}
public class ExecutivesDbContext : DbContext
{
public DbSet<Executives> Executives { get; set; }
}
}
and this too Working Fine in all views(create, edit, delete)
What i need is, i need a Dropdown list of Executive name in Clients View instead of editor Field.
i looked some tutorials but i am confused...
Please help me to solve it...
Seems like you are using EF Code First with MVC.
The simplest answer is that you need to a List of Executives, pass the list in a model back to your View, create a select list, and render a drop down list.
public ActionResult Execx()
{
Model Model = new Model();
Model.execList = dbcontext.Executives;
return View(Model);
}
In your View:
#Html.DropDownListFor(model => model.execId, new SelectList(Model.execList, "ExecutiveId", "ExecutiveName "))
This is untested code. I slapped the pieces together to give you the idea.

Resources