The error that's being thrown: ArgumentNullException: Value cannot be null. (Parameter 'source')
Stacktrace:
ArgumentNullException: Value cannot be null. (Parameter 'source')
System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
System.Linq.Enumerable.Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector)
Checklist.Extensions.IEnumerableExtension.ToSelectListItem<TSource>(IEnumerable<TSource> items, int selectedValue) in IEnumerableExtension.cs
return from item in items
AspNetCore.Areas_Sales_Views_Checklist_Create.<ExecuteAsync>b__29_0() in Create.cshtml
<select asp-for="@Model.Checklists.CustomerId" id="CustomerId" asp-items="Model.Customer.ToSelectListItem(Model.Checklists.CustomerId)" class="form-control"></select>
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
Microsoft.AspNetCore.Mvc.TagHelpers.RenderAtEndOfFormTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count)
AspNetCore.Areas_Sales_Views_Checklist_Create.ExecuteAsync() in Create.cshtml
ViewData["Title"] = "Checklist Aanmaken";
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)
Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
IEnumerableExtensions.cs:
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Checklist.Extensions
{
public static class IEnumerableExtension
{
public static IEnumerable<SelectListItem> ToSelectListItem<T>(this IEnumerable<T> items, int selectedValue)
{
return from item in items
select new SelectListItem
{
Text = item.GetPropertyValue("Name"),
Value = item.GetPropertyValue("Id"),
Selected = item.GetPropertyValue("Id").Equals(selectedValue.ToString())
};
}
ChecklistViewModel.cs:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Checklist.Models.ViewModels
{
public class ChecklistViewModel
{
public ChecklistModel Checklists { get; set; }
public IEnumerable<Customer> Customer { get; set; }
public IEnumerable<CustomerSite> CustomerSite { get; set; }
public IEnumerable<IdentityUser> User { get; set; }
public ChecklistModel.EDeviceCategory DeviceCategory { get; set; }
}
}
ChecklistModel.cs:
[Display(Name = "Customer")]
public int CustomerId { get; set; }
[ForeignKey("CustomerId")]
public virtual Customer Customer { get; set; }
ChecklistController.cs:
using Checklist.Data;
using Checklist.Models;
using Checklist.Models.ViewModels;
using Checklist.Utility;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Checklist.Areas.Sales.Controllers
{
[Area("Sales")]
public class ChecklistController : Controller
{
private readonly ApplicationDbContext _db;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly IEmailSender _emailSender;
[BindProperty]
public ChecklistViewModel ChecklistVM { get; set; }
public ChecklistController(ApplicationDbContext db, IWebHostEnvironment hostingEnvironment, IEmailSender emailSender)
{
_db = db;
_hostingEnvironment = hostingEnvironment;
_emailSender = emailSender;
ChecklistVM = new ChecklistViewModel()
{
Customer = _db.Customer,
Checklists = new Models.ChecklistModel(),
CustomerSite = _db.CustomerSite,
User = _db.IdentityUser
};
}
......
public IActionResult Create()
{
return View(ChecklistVM);
}
[HttpPost, ActionName("Create")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreatePOST()
{
if (int.TryParse(Request.Form["CustomerSiteId"], out int customerSiteId))
{
ChecklistVM.Checklists.CustomerSiteId = Convert.ToInt32(Request.Form["CustomerSiteId"].ToString());
}
ChecklistVM.Checklists.EmployeeId = Request.Form["EmployeeId"].ToString();
var claimsIdentity = (ClaimsIdentity)User.Identity;
var claims = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
ChecklistVM.Checklists.SalesPerson = _db.ApplicationUser.Where(u => u.Id == claims.Value).FirstOrDefault().Name;
ChecklistVM.Checklists.Employee = (_db.ApplicationUser.Where(u => u.Id == Request.Form["EmployeeId"].ToString()).FirstOrDefault().Name);
if (!ModelState.IsValid)
{
return View(ChecklistVM);
}
_db.Checklist.Add(ChecklistVM.Checklists);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
Create.cshtml:
<div class="form-group row">
<div class="col-2">
<label asp-for="Checklists.CustomerId" class="col-form-label-lg">Customer</label>
</div>
<div class="col-5">
<select asp-for="@Model.Checklists.CustomerId" id="CustomerId" asp-items="Model.Customer.ToSelectListItem(Model.Checklists.CustomerId)" class="form-control"></select>
</div>
</div>
How can I find out where this issue is coming from?
The strange thing is that it has worked on my machine earlier and I haven't touched any of this code for a while.
CodePudding user response:
The culprit seems to be in my createPOST() method.
More particular this if statement:
if (!ModelState.IsValid)
{
return View(ChecklistVM);
}
When commenting out this code, all seems to work as expected. Data is created in the database and I get returned to the index page, which displays the newly created item.
So I can conclude that my modelstate is invalid and it returns the view with a model that has null values, and those cause the selectlistitem to fail loading.
The only thing now is figuring out why the modelstate if statements gets triggered...
Edit:
It doesn't make sense now, I saw that I forgot some asp-validation-for tag helpers, so I created those. I then uncommented the modelstate if statement, and tried once again. That seems to have resolved this issue. To further investigate I commented out the validation tags, and tried once again, and it still works... (cleared cache, cookies,...)
EDIT:
The root cause seems to be that I didn't create my DeviceCategory in my ViewModel, which caused the model to be invalid when POST.
public ChecklistModel.EDeviceCategory DeviceCategory { get; set; }