Razor page <input asp-for> only submits as null value for my class' int value, despite entering a value - c#

I cannot seem to use integers with <input asp-for="" /> when creating a new Department instance, the value reverts to null when reaching OnPost(). I have no idea as to what the issue is,
<input asp-for="" /> works fine for the other value types within Department.
Department.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
namespace Scratch.Data
{
public class Department
{
[Key]
public int Id { get; set; }
[Required]
public string departmentName { get; set; }
[Required]
[ForeignKey("AspNetUsers")]
public string departmentManagerId { get; set; }
[AllowNull]
[ForeignKey("AspNetUserRoles")]
public string? managerRoleId;
[AllowNull]
[ForeignKey("AspNetUserRoles")]
public string? userRoleId;
[AllowNull]
public int? defaultDisplayOrder;
}
}
I simplified the code below down to testing for the one input I want to get from the page:
CreateDepartmentIntTestModel
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Build.Evaluation;
using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore;
using Scratch.Data;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Mvc.TagHelpers;
namespace Scratch.Pages.Admin_Tools
{
[BindProperties]
[Authorize(Roles = "Administrators,ProjectManager")]
public class CreateDepartmentIntTestModel : PageModel
{
private readonly ApplicationDbContext _db;
private readonly UserManager<IdentityUser> _userManager;
private readonly IUserStore<IdentityUser> _userStore;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IRoleStore<IdentityRole> _roleStore;
public Department Department { get; set; }
public CreateDepartmentIntTestModel(ApplicationDbContext db, UserManager<IdentityUser> userManager,
IUserStore<IdentityUser> userStore,
RoleManager<IdentityRole> roleManager,
IRoleStore<IdentityRole> roleStore)
{
_db = db;
_userManager = userManager;
_userStore = userStore;
_roleManager = roleManager;
_roleStore = roleStore;
}
public async Task<IActionResult> OnGet()
{
return Page();
}
public async Task<IActionResult> OnPost()
{
//this is always null despite inputs
if (Department.defaultDisplayOrder == null)
{
//add breakpoint here:
ModelState.AddModelError("Department.defaultDisplayOrder", "display order is null");
}
return Page();
}
}
}
Html
#page
#model Scratch.Pages.Admin_Tools.CreateDepartmentIntTestModel
#{
}
<form method="post">
<input hidden asp-for="Department.managerRoleId" />
<input hidden asp-for="Department.userRoleId" />
<div class="border p-3 mt-4">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="row pb-2">
<h2 class="text-primary pl-3">
Test to enter a numeric value to department:
</h2>
</div>
<div class="mb-3">
Department Display Order Value:
<input asp-for="Department.defaultDisplayOrder" class="form-control" />
<span asp-validation-for="Department.defaultDisplayOrder" class="text-danger"></span>
<hr/>
</div>
<button type="submit" class="btn btn-primary" style="width:150px;">Create</button>
</div>
</form>

Your defaultDisplayOrder member is a field, not a property (ref: What is the difference between a field and a property?). Model binding only works with public properties. Add { get; set; } to the declaration to make it a property:
public int? defaultDisplayOrder { get; set; }

Related

Why I the method don't have an acsess to the controller? Blazor Webassembly

#page "/choosedata"
<div class="choose-form">
<input type="text" #bind="p1" /> <span>:מחוז</span>
<br /><br />
<input type="text" #bind="p2" /> <span>:תאריך</span>
<div class="choose-btn">
<a class="btn btn-primary" href="/routeddata/#p1/#p2">Select</a>
</div>
</div>
#code {
string p1 = string.Empty;
string p2 = string.Empty;
}
That page, by clicking Select that page routing to another page by url. that called RoutedData
#page "/routeddata"
#page "/routeddata/{p1}/{p2}"
#using Microsoft.AspNetCore.Components.Forms
#inject HttpClient Http
#inject IJSRuntime JS
#using MyApp.Shared;
<h1>Routed Data Page</h1>
<!--There will be a table that that fetched from SQL server after Post requset-->
<p>#ObjectForShowing</p>
#code {
//What will happens when the blazor page will start?
protected override async Task OnInitializedAsync()
{
ObjectForShowing= await ShowTable();
}
[Parameter]
public string P1 { get; set; }
[Parameter]
public string P2 { get; set; }
private District district = new();
private District ObjectForShowing = new();
public async Task<District> ShowTable()
{
district.DistrictName = P1;
district.PresentationDate = P2;
using var result = await Http.PostAsJsonAsync("RoutedData/ShowData",district);
var content = await result.Content.ReadFromJsonAsync<District>();
return content;
}
}
JsonAsync Mehod doest have any access to controlle URI.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using MyApp.Shared;
namespace MyApp.Server.Controllers;
[ApiController]
[Route("[controller]/[action]")]
public class RoutedDataController : ControllerBase
{
private readonly ILogger<RoutedDataController> _logger;
public RoutedDataController(ILogger<RoutedDataController> logger) => _logger = logger;
[HttpPost]
public District ShowData(District d)
{
return d;
}
}
...............................................................................................
I tried to check the routing and the routing is fine between post method and controller
....................................................................................................

cannot convert between an Identity Class and a local one in ASP.net MVC

I'm currently developing with ASP.NET MVC and after I have created the an error of converting a local class to an Identity one cannot implicitly convert "ListUsers" to "Identity.IdentityUser"(I simplified the error a bit) anyway, here are some bits of code:
ListUsersController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ServiceReferenceAuthentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using SoftSMS.Data.Data;
using SoftSMS.Data.Entities;
using SoftSMS.Data.Entity;
using SoftSMS.Data.Interfaces;
using SoftSMS.MVC.ViewModels;
namespace SoftSMS.MVC.Controllers
{
public class ListUsersController : Controller
{
private readonly DataContext _context;
private readonly RoleManager<IdentityRole> roleManager;
private readonly UserManager<ListUsers> userManager;
private readonly IConfiguration configuration;
private readonly IUnitOfWork<ListUsers> _users;
//private readonly DataContext _context;
public ListUsersController(IUnitOfWork<ListUsers> Users/*DataContext context*/)
{
_users = Users;
//_context = context;
}
// GET: ListUsers
public IActionResult Index()
{
return View(_users.Entity.GetAll());
}
// GET: ListUsers/Details/5
public async Task<IActionResult> DetailsAsync(Guid? id)
{
if (id == null)
{
return NotFound();
}
...
if (listUsers == null)
{
return NotFound();
}
return View(listUsers);
}
// GET: ListUsers/Create
public IActionResult Create()
{
return View();
}
// POST: ListUsers/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,UserName,FirstName,LastName,Status,Profil")] ListUsers listUsers)
{
try
{
TPFAuthenticationSoapClient.EndpointConfiguration endpointConfiguration = new TPFAuthenticationSoapClient.EndpointConfiguration();
TPFAuthenticationSoapClient servAuth = new TPFAuthenticationSoapClient(endpointConfiguration);
if ((Boolean)TempData["isValid"] == false)
{
IdentityUser u = await userManager.FindByNameAsync(listUsers.UserName);
if (u != null)
{
ViewBag.IsValid = false;
ModelState.AddModelError(string.Empty, "Ce Compte existe déja");
}
else
{
...;
if (x != null)
{
...
return View(listUsers);
}
else
{
...
}
}
}
else
{
...
return RedirectToAction(nameof(Index));
}
return View(listUsers);
}
catch (Exception ex)
{
...
return RedirectToAction(nameof(Create));
}
}
the error is in IdentityUser u = await userManager.FindByNameAsync(listUsers.UserName);
I don't want to create an operator override as it's suggested (nor explicit conversion),
ListUsers.cs:
using Microsoft.AspNet.Identity.EntityFramework;
using SoftSMS.Data.Entities;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
namespace SoftSMS.Data.Entity
{ public enum StatusType
{ Banned,Registered,Normal,Warned}
public enum ProfilType
{ Admin,Manager,Agent}
public class ListUsers : IdentityUser
{
[DataType(DataType.Text)]
public string FirstName { get; set; }
[DataType(DataType.Text)]
public string LastName { get; set; }
[DataType(DataType.Text)]
[Required]
public StatusType Status { get; set; }
public ProfilType Profil { get; set; }
public virtual ICollection<MembershipAssociations> MembershipAssociation { get; set; }
public virtual ICollection<Template> TemplateNavigation { get; set; }
public virtual ICollection<SentMsg> SentmsgNavigation { get; set; }
}
}
UsersViewModel.cs:
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace SoftSMS.MVC.ViewModels
{ public enum StatusType
{ Banned,Registered,Normal,Warned}
public enum ProfilType
{ Admin,Manager,Agent}
public class UsersViewModel : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public StatusType Status { get; set; }
public ProfilType Profil { get; set; }
public List<MembershipAssociationViewModel> MembershipAssociation { get; set; }
public List<SentMsgViewModel> Sentmsg { get; set; }
}
}
and Create.cshtml:
#model SoftSMS.MVC.ViewModels.UsersViewModel
#{ ViewData["Title"] = "Create"; }
#{TempData["isValid"] = ViewBag.isValid;}
<br />
<h3>Nouvel Utilisateur</h3>
<hr />
#*#ViewBag.Result1*#
<br />
<h4 style="color: red;">#TempData["errorMessage"]</h4>
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
#if ((Boolean)ViewBag.isValid == false)
{
<div class="form-group">
<label asp-for="UserName" class="control-label">Login</label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div> }
#if ((Boolean)ViewBag.isValid == true)
{
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="UserName" class="control-label">Login</label>
<input asp-for="UserName" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.UserName)
</div>
<div class="form-group">
<label asp-for="FirstName" class="control-label">Prenom</label>
<input asp-for="FirstName" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.FirstName)
</div>
<div class="form-group">
<label asp-for="LastName" class="control-label">Nom</label>
<input asp-for="LastName" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.LastName)
</div>
<div class="form-group">
<label asp-for="Email" class="control-label">Email</label>
<input asp-for="Email" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.Email)
</div>
<div class="form-group">
<label asp-for="EstActif" class="control-label">Actif</label>
<select id="Select1" asp-for="EstActif" class="form-control">
<option value="True"> <text>OUI</text></option>
<option value="False"> <text>NON</text></option>
</select>
</div> }
<div class="form-group">
<input type="submit" value="Creer" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Liste des utilisateurs</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
as you could have seen, I had to make the UI in French (even though I don't like it) because I am developing this platform for French people,
if you need another resource, I could share it, but not the entire app, the ...is for a confidential code,
thank you

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

How to create dropdown from model?

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

Facing Object reference not set exception even though operation succeeding [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
I'm getting the following error each Time I try to enter a new Course.
Object reference not set to an instance of an object.
AspNetCore._Views_Admin_Manage_cshtml+<b__23_12>d.MoveNext()
in Manage.cshtml, line 34
Here is my Controller:
using ASP_Project.Data;
using ASP_Project.Models;
using ASP_Project.Services.Interfaces;
using ASP_Project.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace ASP_Project.Controllers
{
public class AdminController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SchoolContext _schoolContext;
private readonly IAdminRepository _adminRepos;
private readonly ITeacherRepository _teacherRepository;
public AdminController(UserManager<ApplicationUser> userManager,
SchoolContext schoolContext,
IAdminRepository adminRepos,
ITeacherRepository teacherRepository
)
{
_userManager = userManager;
_schoolContext = schoolContext;
_adminRepos = adminRepos;
_teacherRepository = teacherRepository;
}
[HttpGet]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Index()
{
ClaimsPrincipal currentUser = User;
var user = await _userManager.GetUserAsync(currentUser);
var admin = _adminRepos.GetAdminByUser(user);
return View(new AdminViewModel()
{
FirstName = admin.FirstName,
LastName = admin.LastName,
MiddleName = admin.MiddleName
});
}
[HttpGet]
public IActionResult Manage()
{
IEnumerable<string> teachers = _teacherRepository.TeacherNames();
return View(new CourseViewModel()
{
Teachers = teachers
});
}
[HttpPost]
public async Task<IActionResult> Manage(CourseViewModel courseViewModel)
{
var teacher = _schoolContext.Teacher.Single(t => t.FirstName == courseViewModel.TeacherName);
Course course = new Course()
{
CodeID = courseViewModel.CodeID,
Name = courseViewModel.Name,
NumOfCredits = courseViewModel.NumOfCredits,
TeacherID = teacher.TeacherID
};
await _schoolContext.Course.AddAsync(course);
if (await _schoolContext.SaveChangesAsync() == 0)
return RedirectToAction("Index", "Admin");
return View(courseViewModel);
}
}
}
Here is my View:
#model ASP_Project.ViewModels.CourseViewModel
#{
ViewData["Title"] = "Manage";
}
<h2>Manage</h2>
<div class="row">
<div class="col-md-4">
<form asp-controller="Admin" asp-action="Manage" method="post" class="form-horizontal" role="form">
<h4>Create a new Course.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="CodeID"></label>
<input asp-for="CodeID" class="form-control" />
<span asp-validation-for="CodeID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NumOfCredits"></label>
<input asp-for="NumOfCredits" class="form-control" />
<span asp-validation-for="NumOfCredits" class="text-danger"></span>
</div>
<div>
<label asp-for="TeacherName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="TeacherName" class="form-control" required>
<option value="" disabled selected>Select Teacher</option>
#foreach (var teach in Model.Teachers)
{
<option value="#teach"> #teach </option>
}
</select>
<span asp-validation-for="TeacherName" class="text-danger"></span>
</div>
</div>
<button type="submit" class="btn btn-default">Add</button>
</form>
</div>
</div>
#section Scripts {
#await Html.PartialAsync("_ValidationScriptsPartial")
}
My CourseViewModel:
using ASP_Project.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace ASP_Project.ViewModels
{
public class CourseViewModel
{
[Required]
public string CodeID { get; set; }
[Required]
public int NumOfCredits { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string TeacherName { get; set; }
public IEnumerable<string> Teachers { get; set; }
}
}
And Finally the Function used to retrieve the names of the teachers:
public IEnumerable<string> TeacherNames() => _schoolContext.Teacher.Select(t => t.FirstName);
What I understood from the exception is that there is either a part of the foreach that needs an await or that one of the Objects is not being defined.
Take note that the operation is doing its job successfully nonetheless and the data is being added to the database, its just that this strange exception keeps showing up.
Edit: Even though #NoCodeFound answer Pointed out that I should debug (and that's what I did to find the answer) yet I was planning on doing that anyway, and I happened to discover the real cause anyway.
Turns out I messed up when I return from the Manage action after POST, since I used:
if (await _schoolContext.SaveChangesAsync() == 0)
return RedirectToAction("Index", "Admin");
return View(courseViewModel);
which was making me go through the courseViewModel again rather than being redirected to the page I needed.
So the fix would simply be:
if (await _schoolContext.SaveChangesAsync() == 0)
return View(courseViewModel);
return RedirectToAction("Index", "Admin");

Categories