You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AspNet Core下拉列表绑定问题:分部视图正常但控制器执行异常

Fixing Model Binding Exception with Read-Only ShortInfo and Dropdown Binding

Let's break down the issue you're facing and walk through the fixes step by step.

What's Causing the Exception?

From your description, there are two likely culprits:

  1. Incorrect asp-items Binding: You're passing a list of ShortInfo directly to asp-items, which expects an IEnumerable<SelectListItem>. While ASP.NET Core might do an implicit conversion in some cases, this can lead to inconsistent behavior and binding issues.
  2. Model Binding Tries to Hydrate Info List: When you submit the form, the model binder attempts to populate the entire SelectSomething model—including the Info list of ShortInfo objects. Since ShortInfo has read-only properties and no parameterless constructor, the binder can't instantiate new ShortInfo instances, triggering an exception.

Step 1: Correct the Dropdown List Binding

First, explicitly convert your ShortInfo list to a SelectList (or List<SelectListItem>) to ensure the dropdown works reliably. This makes the binding logic clear and avoids implicit conversion quirks.

Update your partial view code like this:

@model SelectSomething

<div class="form-group">
    <label asp-for="Id" class="control-label">Select an Item</label>
    <select asp-for="Id" class="form-control"
            asp-items="@new SelectList(Model.Info, nameof(ShortInfo.Id), nameof(ShortInfo.FullName))">
        <option value="">-- Choose an option --</option>
    </select>
    <span asp-validation-for="Id" class="text-danger"></span>
</div>

This explicitly tells the framework to use ShortInfo.Id as the option value and ShortInfo.FullName as the display text.

Step 2: Prevent Model Binding for the Info List

Since you only need the selected Id in your controller (not the entire Info list), we need to tell the model binder to ignore the Info property during POST requests. You have two clean ways to do this:

Option A: Use the [BindNever] Attribute

Add the [BindNever] attribute to the Info property in your SelectSomething class. This instructs the model binder to skip binding this property entirely:

using Microsoft.AspNetCore.Mvc.ModelBinding;

public class SelectSomething
{
    public int Id { get; set; }

    [BindNever]
    public List<ShortInfo> Info { get; set; }
}

Option B: Use a ViewModel for Separation of Concerns

For a more robust approach (especially if your application grows), create a dedicated view model that separates display data from bindable data:

// ViewModel for displaying the dropdown
public class SelectSomethingViewModel
{
    public int SelectedItemId { get; set; }
    public List<ShortInfo> ItemOptions { get; set; }
}

// Your existing domain classes remain unchanged
public class ShortInfo
{
    public int Id { get; }
    public string FullName { get; }

    public ShortInfo(int id, string fullName)
    {
        Id = id;
        FullName = fullName;
    }
}

Update your partial view to use this view model:

@model SelectSomethingViewModel

<div class="form-group">
    <label asp-for="SelectedItemId" class="control-label">Select an Item</label>
    <select asp-for="SelectedItemId" class="form-control"
            asp-items="@new SelectList(Model.ItemOptions, nameof(ShortInfo.Id), nameof(ShortInfo.FullName))">
        <option value="">-- Choose an option --</option>
    </select>
    <span asp-validation-for="SelectedItemId" class="text-danger"></span>
</div>

Then in your controller, handle GET and POST requests separately:

// GET: Populate the view model with options
public IActionResult LoadPartial()
{
    var viewModel = new SelectSomethingViewModel
    {
        ItemOptions = GetShortInfoItems() // Replace with your data retrieval logic
    };
    return PartialView("_YourPartialViewName", viewModel);
}

// POST: Only accept the selected ID
[HttpPost]
public IActionResult ProcessSelection(int selectedItemId)
{
    // Handle the selected ID here
    return RedirectToAction("Index");
}

Why This Works

  • The explicit SelectList conversion ensures the dropdown renders correctly with the right value/text pairs.
  • By ignoring the Info list (either via [BindNever] or a view model), we avoid the model binder trying to instantiate read-only ShortInfo objects during POST, eliminating the exception.

内容的提问来源于stack exchange,提问作者Luca Mori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:42:40