How to create dropdown from model? - c#

I have two models:
public class Question
{
public int Id { get; set; }
public string Title { get; set; }
public int ClosedReasonId { get; set; }
public CloseReasonType CloseReasonType { get; set; }
}
public class CloseReasonType
{
public int Id { get; set; }
public string Name { get; set; }
public List<Question> Questions { get; set; }
}
I would like to create a view which has a form for adding questions and a dropdown for CloseReasonType.
#page
#model RazorPagesQuestion.Pages.Questions.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Question</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Question.Title" class="control-label"></label>
<input asp-for="Question.Title" class="form-control" />
<span asp-validation-for="Question.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Question.CloseReasonType" class="control-label"></label>
<select asp-for="Question.CloseReasonType" class="form-control"
asp-items="Model.CloseReasonType">
</select>
<span asp-validation-for="Question.CloseReasonType" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Of course when I just added asp-items="Model.CloseReasonType" to my select tag helper it didn't populate the dropdown with options. How can I populate the options?
I added this to my CreateModel class
[BindProperty]
public Question Question { get; set; }
[BindProperty]
public List<SelectListItem> CloseReasonType { get; }
All the examples I have seen show how to create the list out of hardcoded values.
The full class:
public class CreateModel : PageModel
{
private readonly RazorPagesQuestion.Data.RazorPagesQuestionContext _context;
public CreateModel(RazorPagesQuestion.Data.RazorPagesQuestionContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Question Question { get; set; }
[BindProperty]
public List<SelectListItem> CloseReasonType { get; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Question.Add(Question);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}

You would need to populate the select list for it to display on the page
Assuming your DbContext has a CloseReasonTypes property
//...
private void loadCloseReasonTypes() {
CloseReasonTypes = new SelectList(_context.CloseReasonTypes, nameof(CloseReasonType.Id), nameof(CloseReasonType.Name));
}
public IActionResult OnGet() {
loadCloseReasonTypes();
return Page();
}
public SelectList CloseReasonTypes { get; set; }
[BindProperty]
public Question Question { get; set; }
//...
Update the view to bind to the relevant property on the model.
<div class="form-group">
<label asp-for="Question.CloseReasonId" class="control-label">Close Reason</label>
<select asp-for="Question.CloseReasonId" class="form-control"
asp-items="Model.CloseReasonTypes">
</select>
<span asp-validation-for="Question.CloseReasonId" class="text-danger"></span>
</div>
The list will also need to be repopulated if the post was not successful as the page will reload, clearing the select list.
public async Task<IActionResult> OnPostAsync() {
if (!ModelState.IsValid) {
loadCloseReasonTypes();
return Page();
}
_context.Question.Add(Question);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

Related

ASP.NET Tag helpers and Bootstrap Dropdown. How to use together?

Faced such peculiar problem. For a better understanding, I will try to describe in more detail.
I have two metod in ArticleController:
[HttpGet]
public async Task<IActionResult> Create()
{
var sources = await _sourceServices.GetSourceNameAndId();
var listSources = new List<SourceNameAndIdModel>();
foreach (var source in sources)
{
listSources.Add(_mapper.Map<SourceNameAndIdModel>(source));
}
var viewModel = new ArticleCreateViewModel()
{
SourceNameAndIdModels = listSources
};
return View(viewModel);
}
[HttpPost]
public async Task<IActionResult> Create(ArticleCreateViewModel viewModel)
{
await _articleService.CreateArticle(_mapper.Map<ArticleDTO>(viewModel));
return RedirectToAction("Index", "Article");
}
As you can see, in the Get-method, I get the names and ids of all Sources from the database via _sourceService in the form of IEnumerable :
public class SourceNameAndIdDTO
{
public Guid Id { get; set; }
public string Name { get; set; }
}
Next, I enumerate them in a foreach loop and add each SourceNameAndIdDTO object to the List listSources I created before:
public class SourceNameAndIdModel
{
public string Name { get; set; }
public Guid Id { get; set; }
}
Next, I create an instance of the ArticleCreateViewModel model, which I will use further in the View:
public class ArticleCreateViewModel
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Title { get; set; }
public string Description { get; set; }
public string Body { get; set; }
public Guid SourceId { get; set; }
public DateTime CreationDate { get; set; }
public List<SourceNameAndIdModel> SourceNameAndIdModels { get; set; }
}
And I assign to the field public List SourceNameAndIdModels { get; set; } List listSources values:
var viewModel = new ArticleCreateViewModel()
{
SourceNameAndIdModels = listSources
};
You can see this in the controller code I posted above. Next, I send the viewModel to the View.
Code of my View:
#model ArticleCreateViewModel
<div class="container">
<h2>Edit article</h2>
<div class="row gx-5">
<form asp-controller="Article" asp-action="Create" asp-antiforgery="true" method="post">
<div>
<input type="hidden" asp-for="Id" />
<div class="mb-3">
<label class="col-sm-2 col-form-label" asp-for="Title"></label>
<input class="form-control" type="text" asp-for="Title">
</div>
<div class="mb-3">
<label class="col-sm-2 col-form-label" asp-for="Description"></label>
<textarea class="form-control" asp-for="Description"></textarea>
</div>
<div class="mb-3">
<label class="col-sm-2 col-form-label" asp-for="Body"></label>
<textarea class="form-control" asp-for="Body"></textarea>
</div>
<div class="dropdown">
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Source
</a>
<ul class="dropdown-menu">
#foreach (var item in #Model.SourceNameAndIdModels)
{
<li><select class="dropdown-item" asp-for="SourceId" asp-items="#item.Id">#item.Name</select></li>
}
</ul>
</div>
<div class="mb-3">
<label class="col-sm-2 col-form-label" asp-for="CreationDate"></label>
<input type="datetime-local" class="form-control" asp-for="CreationDate">
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
And finally, in this place of the code, in which I want to set the Source of the article I am creating, I have an error:
enter image description here
Can you please tell me how in my case to make friends with my code with dropdown on my request? What am I doing wrong?
Using asp-items in this way is incorrect.
The Select Tag Helper asp-items specifies the option elements
Details and example:
https://learn.microsoft.com/...netcore-6.0#the-select-tag-helper

Automatically select the options of multiple selection drop down for the edit page in ASP.NET Core 6.0 Razor Pages

I am beginner in ASP.NET Core. I need help with automatically selecting the options of a multi-selection dropdown.
I have a class model and a class can have multiple students. When I am creating the class, I have a dropdown that shows the student list and I can add the students to the class by selecting the options form the drop down.
But I am having issues automatically selecting those values for the edit page. The dropdown should keep those students selected from the list when the edit page loads so that the user can see which students are currently enrolled in the class. I am only seeing the students that are enrolled in the class as option of the dropdown. It should show all the students in the list but select the ones that belongs to the class.
My class model:
public class ClassModel
{
[Key]
[Required]
[Display(Name ="Class ID")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ClassID { get; set; }
//[ForeignKey("UserProfile")]
//[Display(Name = "User ID")]
//public virtual int ID { get; set; }
[Required]
public string Description { get; set; }
[Required]
public int Occurence { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime Startdate { get; set; }
[Required]
[DataType(DataType.Time)]
public DateTime From { get; set; }
[Required]
[DataType(DataType.Time)]
//[GreaterThanOrEqualTo("From")]
public DateTime To { get; set; }
[Required]
[DataType(DataType.Currency)]
public double Fees { get; set; }
[DisplayFormat(NullDisplayText = "No Instructor Assigned")]
[ForeignKey("InstructorID")]
public virtual int InstructorID { get; set; }
public Instructor? Instructor { get; set; }
// [DisplayFormat(NullDisplayText = "No Student Assigned")]
[NotMapped]
public ICollection<int> StudentID { get; set; }
public ICollection<Enrollment>? Enrollment { get; set; }
}
EditClass.cshtml.cs code:
public class EditModel : PageModel
{
private readonly TestProject.Data.TestProjectContext _context;
public EditModel(TestProject.Data.TestProjectContext context)
{
_context = context;
}
[BindProperty]
public Model.ClassModel Class_Info { get; set; }
[BindProperty]
public ClassModelStudent Class_Student { get; set; }
public Model.Instructor instructor { get; set; }
public SelectList Instructors { get; set; }
public SelectList Students { get; set; }
public MultiSelectList Class_Student { get; set; }
public SelectList SelectedStudents { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Class_Info = await _context.Class.FirstOrDefaultAsync(m => m.ClassID == id);
var instructors = from i in _context.Instructor
orderby i.FirstName
select i;
Instructors = new SelectList(instructors, "InstructorID", "FirstName");
var selectedstudents = from cs in _context.ClassModelStudent
join s in _context.User_Profile on cs.StudentsStudentID equals s.StudentID
select new { cs.StudentsStudentID, s.FullName, s.PhoneNumber };
SelectedStudents = new SelectList(selectedstudents, "StudentsStudentID", "FullName");
Class_Student = SelectedStudents;
var students = from cs in _context.ClassModelStudent
join s in _context.User_Profile on cs.StudentsStudentID equals s.StudentID
select new { cs.StudentsStudentID, s.FullName, s.PhoneNumber };
Students = new SelectList(students, "StudentsStudentID", "FullName", "PhoneNumber");
// Class_Student.StudentsStudentID = id;
//from s in _context.ClassModelStudent
// orderby s.StudentsStudentID
// select s;
if (Class_Info == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Class_Info).State = EntityState.Modified;
_context.Attach(Class_Student).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!Class_InfoExists(Class_Info.ClassID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool Class_InfoExists(int id)
{
return _context.Class.Any(e => e.ClassID == id);
}
}
EditClass.cshtml view markup:
#page
#model TestProject.Pages.Classes.EditModel
#{
ViewData["Title"] = "Edit";
Layout = "~/Pages/Shared/_Layout.cshtml";
}
<h1>Edit</h1>
<h4>Class_Info</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Class_Info.ClassID" />
#*<div class="form-group">
<label asp-for="Class_Info.ID" class="control-label"></label>
<input asp-for="Class_Info.ID" class="form-control" />
<span asp-validation-for="Class_Info.ID" class="text-danger"></span>
</div>*#
<div class="form-group">
<label asp-for="Class_Info.Description" class="control-label"></label>
<input asp-for="Class_Info.Description" class="form-control" />
<span asp-validation-for="Class_Info.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Class_Info.Occurence" class="control-label"></label>
<input asp-for="Class_Info.Occurence" class="form-control" />
<span asp-validation-for="Class_Info.Occurence" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Class_Info.Startdate" class="control-label"></label>
<input asp-for="Class_Info.Startdate" class="form-control" />
<span asp-validation-for="Class_Info.Startdate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Class_Info.From" class="control-label"></label>
<input asp-for="Class_Info.From" class="form-control" />
<span asp-validation-for="Class_Info.From" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Class_Info.To" class="control-label"></label>
<input asp-for="Class_Info.To" class="form-control" />
<span asp-validation-for="Class_Info.To" class="text-danger"></span>
</div>
<div class="form-group">
#* <label asp-for="instructor.FirstName" class="control-label"></label>
<input asp-for="instructor.FirstName" class="form-control" />*#
<label asp-for="Class_Info.InstructorID" class="control-label"></label>
<select asp-for="Class_Info.InstructorID" class="form-control" asp-items="#Model.Instructors">
<option value="">-- Select --</option>
</select>
<span asp-validation-for="Class_Info.InstructorID" class="text-danger"></span>
</div>
<div class="form-group">
#* <label asp-for="instructor.FirstName" class="control-label"></label>
<input asp-for="instructor.FirstName" class="form-control" />*#
-- Select --
<div>
<a asp-page="./Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Please advise. I would really appreciate your help.

Can't update value: 'Primary Key' has a temporary value while attempting to change the entity's state to 'Modified'

This is my first ASP .Net Core project. It will hold directors. Each director has a page that shows a list of his/her movies.
I have two classes.
Movie:
public class Movie
{
public int MovieId { get; private set; }
public int DirectorId { get; set; }
[Required]
public string Title { get; set; }
public string Year { get; set; }
public string Description { get; set; }
}
And Director:
public class Director
{
public Director()
{
Movies = new List<Movie>();
}
public int DirectorId { get; private set; }
[Required]
public string Name { get; set; }
public string Country { get; set; }
public string Bio { get; set; }
public List<Movie> Movies { get; set; }
}
But I have a problem with editing Directors. As I want to save changes I get this error:
InvalidOperationException: The property 'DirectorId' on entity type
'Director' has a temporary value while attempting to change the
entity's state to 'Modified'. Either set a permanent value explicitly
or ensure that the database is configured to generate values for this
property.
I use this line of code in Index page to navigate to Edit page:
<a asp-page="./../Movies/Create" asp-route-DirectorId="#item.DirectorId">Add Movie</a>
Photo of Index page:
Please click to see the photo
The code in Edit.cshtml.cs:
public class EditModel : PageModel
{
private readonly MastersOfCinema.Data.Context _context;
public EditModel(MastersOfCinema.Data.Context context)
{
_context = context;
}
[BindProperty]
public Director Director { get; set; }
public async Task<IActionResult> OnGetAsync(int? directorId)
{
if (directorId == null)
{
return NotFound();
}
Director = await _context.Director.FirstOrDefaultAsync(m => m.DirectorId == directorId);
if (Director == null)
{
return NotFound();
}
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Director).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!DirectorExists(Director.DirectorId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool DirectorExists(int id)
{
return _context.Director.Any(e => e.DirectorId == id);
}
}
Apparently, Something upsets this very line:
_context.Attach(Director).State = EntityState.Modified;
Perhaps it is about the primary key (DirectorId), As the error suggests.
Edit page screenshot:
Please Click to see Edit page
Edit.cshtml :
#page
#model MastersOfCinema.Pages.Directors.EditModel
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Director</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Director.DirectorId" class="control-label"></label>
<input asp-for="Director.DirectorId" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Director.Name" class="control-label"></label>
<input asp-for="Director.Name" class="form-control" />
<span asp-validation-for="Director.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Director.Country" class="control-label"></label>
<input asp-for="Director.Country" class="form-control" />
<span asp-validation-for="Director.Country" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Director.Bio" class="control-label"></label>
<input asp-for="Director.Bio" class="form-control" />
<span asp-validation-for="Director.Bio" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Additional information:
Context.cs (Uses EF Core) :
public class Context : DbContext
{
public Context (DbContextOptions<Context> options)
: base(options)
{
}
public DbSet<MastersOfCinema.Models.Director> Director { get; set; }
public DbSet<MastersOfCinema.Models.Movie> Movie { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
"Data Source = (localdb)\\MSSQLLocalDB; Initial Catalog = MastersOfCinama");
}
}
Thanks for reading and for any help.
Try removing the private setter from:
public int DirectorId { get; private set; }
Instead it should look like this:
public int DirectorId { get; set; }

How to manage NullReferenceException?

I want to make a form that user have to fill out it.
But I'm getting an error.
Model:
public UserReport Input;
[Key]
//[Required]
public string ReportID { get; set; }
[Required]
public string Description { get; set; }
[Required]
[DataType(DataType.DateTime)]
public string Date { get; set; }
Controller:
private ApplicationDbContext _userReport;
public UserReport Input;
public PageController(ApplicationDbContext userReport)
{
_userReport = userReport;
}
[HttpGet]
public IActionResult SendReport()
{
return View();
}
[Authorize]
[HttpPost]
public async Task<IActionResult> SendReport(UserReport userReport)
{
var user = new UserReport { Description = Input.Description, Date = Input.Date };
var r = await _userReport.AddAsync(user);
}
View:
#model UserReport
<div class="col-md-6">
<form id = "SendReport" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Description"></label>
<input asp-for="Input.Description" class="form-control" />
<span asp-validation-for="Input.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Date"></label>
<input asp-for="Input.Date" class="form-control" />
<span asp-validation-for="Input.Date" class="text-danger"></span>
</div>
<button type = "submit" class="btn btn-primary">send report</button>
</form>
</div>
what is wrong with that?
It shows me this Error :System.NullReferenceException - Object reference not set to an instance of an object... who can help me to manage this error.
Show me where is my mistake please
I think you need to go back through the tutorials in the docs again. It doesn't seem like you really know what you're doing here. You've got a field named Input, which seems to be pulled from a Razor Page, but you're working in an MVC controller here. However, even that is off, because you'd typically see that as something like:
[BindProperty]
public UserReport Input { get; set; }
In a Razor Page. Here, it's not even a property, so even if this would normally do something, it wouldn't as a field, regardless.
The NullReferenceException comes because you reference this field, but never actually initialize it. Again, in a Razor Page (and if it was a property rather than a field), this would get filled with the post data (via BindProperty), but it doesn't work that way in a controller.
In your controller action, you've got a userReport param, so that is where the post data will go. However, since all the asp-for attributes in your view reference Input.Something, nothing will actually get bound to this param. This too seems to be pulled from a Razor Page, without considering that it only works this way in a Razor Page.
Long and short, it looks like you just copied code from other places, without actually understanding any of it or what it does, and cobbled it together into a controller and view. The whole thing is fundamentally broken top-down.
You have mixed with MVC and Razor Pages.
For MVC:
1.Model:
public class UserReport
{
[Key]
//[Required]
public string ReportID { get; set; }
[Required]
public string Description { get; set; }
[Required]
[DataType(DataType.DateTime)]
public string Date { get; set; }
}
2.SendReport.cshtml:
#model UserReport
<div class="col-md-6">
<form asp-action="SendReport" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Description"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Date"></label>
<input asp-for="Date" class="form-control" />
<span asp-validation-for="Date" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">send report</button>
</form>
</div>
3.Controller:
public class UserReportsController : Controller
{
private readonly YourDbContext _context;
public UserReportsController(YourDbContext context)
{
_context = context;
}
public IActionResult SendReport()
{
return View();
}
[HttpPost]
public async Task<IActionResult> SendReport([Bind("ReportID,Description,Date")] UserReport userReport)
{
if (ModelState.IsValid)
{
_context.Add(userReport);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(userReport);
}
}
For Razor Pages:
1.Model:
public class UserReport
{
[Key]
//[Required]
public string ReportID { get; set; }
[Required]
public string Description { get; set; }
[Required]
[DataType(DataType.DateTime)]
public string Date { get; set; }
}
2.SendReport.cshtml:
#page
#model SendReportModel
<div class="col-md-6">
<form id="SendReport" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Description"></label>
<input asp-for="Input.Description" class="form-control" />
<span asp-validation-for="Input.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Date"></label>
<input asp-for="Input.Date" class="form-control" />
<span asp-validation-for="Input.Date" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">send report</button>
</form>
</div>
3.SendReport.cshtml.cs:
public class SendReportModel : PageModel
{
private readonly YourDbContext _context;
public SendReportModel(YourDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public UserReport Input { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.UserReport.Add(Input);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Reference:
Tutorial:Create a web app with ASP.NET Core MVC
Tutorial: Create a Razor Pages web app with ASP.NET Core

ASP.NET MVC Create, Edit and Delete using ViewModel

For whatever reason I'm unable to Create and Edit using the ViewModel called CreateEmployeeViewModel that I created. I can however Create and Edit fine without using the CreateEmployeeViewModel but was told it was bad practive to use the main Models for CRUD. I am however able to retrieve values to my 2 DropDownList tags fine using the CreateEmployeeViewModel, just not Create or Edit. Below are my current Models, ViewModels, Controllers and Views.
I just figure out why I cannot Create using the public IActionResult Create(Employee employee) Active Method.
Employee Model: (located in Models folder)
public class Employee
{
[Key]
public int EmpId { get; set; }
[Required]
public string EmpFirstName { get; set; }
[Required]
public string EmpLastName { get; set; }
public int DeptId { get; set; }
public Department Department { get; set; }
public int BldgId { get; set; }
public Building Building { get; set; }
}
EmployeeController: (located in Controllers folder)
public class EmployeeController : Controller
{
private DataEntryContext _context;
public EmployeeController(DataEntryContext context)
{
_context = context;
}
public IActionResult Index()
{
return View(_context.Employees.ToList());
}
// Populate Department values to DropDownList
private IEnumerable<SelectListItem> GetDeptList()
{
var dept = _context.Departments
.Select(s => new SelectListItem
{
Value = s.DeptId.ToString(),
Text = s.DeptTitle
})
.ToList();
return (dept);
}
// Populate Building values to DropDownList
private IEnumerable<SelectListItem> GetBldgList()
{
var bldg = _context.Buildings
.Select(b => new SelectListItem
{
Value = b.BldgId.ToString(),
Text = b.BldgName
})
.ToList();
return (bldg);
}
public IActionResult Create()
{
CreateEmployeeViewModel model = new CreateEmployeeViewModel();
model.DeptList = GetDeptList();
model.BldgList = GetBldgList();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Employee employee)
{
if (ModelState.IsValid)
{
_context.Employees.Add(employee);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
public IActionResult Edit(int? id)
{
if (id == null)
{
return View("Error");
//return NotFound();
}
var employee = _context.Employees
.Where(e => e.EmpId == id)
.Single();
if (employee == null)
{
return View("Error");
//return NotFound();
}
return View(employee);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(Employee employee)
{
if (ModelState.IsValid)
{
_context.Employees.Update(employee);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
}
CreateEmployeeViewModel: (located in ViewModels Folder)
public class CreateEmployeeViewModel
{
public int EmpId { get; set; }
public string EmpFirstName { get; set; }
public string EmpLastName { get; set; }
public int DeptId { get; set; }
public IEnumerable<SelectListItem> DeptList { get; set; }
public int BldgId { get; set; }
public IEnumerable<SelectListItem> BldgList { get; set; }
}
Employee Create View:
<form asp-controller="employee" asp-action="Create" method="post" class="form-horizontal" role="form">
<div class="form-horizontal">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="EmpFirstName" class="col-md-2 control-label">First Name</label>
<div class="col-md-10">
<input asp-for="EmpFirstName" class="form-control" />
<span asp-validation-for="EmpFirstName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="EmpLastName" class="col-md-2 control-label">Last Name</label>
<div class="col-md-10">
<input asp-for="EmpLastName" class="form-control" />
<span asp-validation-for="EmpLastName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="DeptId" class="col-md-2 control-label">Department</label>
<div class="col-md-10">
<select asp-for="DeptId" asp-items="#Model.DeptList" class="form-control">
<option>Select Department</option>
</select>
<span asp-validation-for="DeptId" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="BldgId" class="col-md-2 control-label">Building Location</label>
<div class="col-md-10">
<select asp-for="BldgId" asp-items="#Model.BldgList" class="form-control">
<option>Select Building</option>
</select>
<span asp-validation-for="BldgId" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
In your Create method, you are sending to the view the CreateEmployeeViewModel but in your HttpPost Create method you are accepting back the Employee model instead of the CreateEmployeeViewModel. So once you change the post methods signature to accept the correct CreateEmployeeViewModel, you can simply map it back to the Employee model.
Get Action Method:
public IActionResult Create(Employee employee)
{
return View(employee);
}
Just change in your Post Action Method:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(CreateEmployeeViewModel vm)
{
if (ModelState.IsValid)
{
var model = new Employee{
//your logic here for example
employeename = vm.employeename,
employeepassword = vm.employeepassword
}
_context.Employees.Add(model);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
and donĀ“t forget to cal View Model in your .cshtml

Categories