ASP.NET MVC含禁用项DropdownList问题及实体表关联咨询
Hey Kevin, let's break down how to solve this problem step by step. First, I'll assume your TransactionCode entity has a flag (like IsActive) to determine which items should be disabled in the dropdown—adjust the condition to match your actual business rules.
1. Ensure Proper Entity Relationship Setup
First, make sure your File entity correctly references the TransactionCode table (since your code was cut off, here's the complete setup):
public class File { [Display(Name = "EcommerceFile_Id", ResourceType = typeof(Resources.ModelResources))] public int Id { get; set; } [Display(Name = "EcommerceFile_FileNumber", ResourceType = typeof(Resources.ModelResources))] public string FileNumber { get; set; } // Foreign key to TransactionCodes table [Display(Name = "EcommerceFile_TransactionCodeId", ResourceType = typeof(Resources.ModelResources))] public int TransactionCodeId { get; set; } // Navigation property for EF Core/EF6 public virtual TransactionCode TransactionCode { get; set; } } public class TransactionCode { public int Id { get; set; } public string Code { get; set; } public bool IsActive { get; set; } // Use this to mark items as disabled/enabled }
2. Create a ViewModel for the View
Using a ViewModel keeps your view clean and separates concerns:
public class FileViewModel { public int Id { get; set; } public string FileNumber { get; set; } public int SelectedTransactionCodeId { get; set; } public IEnumerable<SelectListItem> TransactionCodeOptions { get; set; } }
3. Populate the ViewModel in the Controller
In your controller action, fetch the transaction codes and map them to SelectListItem with the Disabled property set based on your condition:
public ActionResult Edit(int id) { var file = _dbContext.Files.Find(id); if (file == null) return HttpNotFound(); // Fetch all transaction codes and mark inactive ones as disabled var transactionCodeOptions = _dbContext.TransactionCodes .Select(tc => new SelectListItem { Value = tc.Id.ToString(), Text = tc.Code, Disabled = !tc.IsActive, // Disable inactive codes Selected = tc.Id == file.TransactionCodeId }).ToList(); var viewModel = new FileViewModel { Id = file.Id, FileNumber = file.FileNumber, SelectedTransactionCodeId = file.TransactionCodeId, TransactionCodeOptions = transactionCodeOptions }; return View(viewModel); }
4. Render the DropDownList with Disabled Items
The standard DropDownListFor helper doesn't automatically render the disabled attribute from SelectListItem, so we'll build the select element manually:
@model FileViewModel <div class="form-group"> @Html.LabelFor(m => m.SelectedTransactionCodeId, new { @class = "control-label" }) <select id="SelectedTransactionCodeId" name="SelectedTransactionCodeId" class="form-control"> @foreach (var option in Model.TransactionCodeOptions) { <option value="@option.Value" @(option.Selected ? "selected" : "") @(option.Disabled ? "disabled" : "")> @option.Text </option> } </select> @Html.ValidationMessageFor(m => m.SelectedTransactionCodeId) </div>
5. Server-Side Validation (Critical!)
Client-side disabled items can be bypassed by modifying the HTML, so always validate on the server:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit(FileViewModel viewModel) { if (!ModelState.IsValid) { // Repopulate options if validation fails viewModel.TransactionCodeOptions = _dbContext.TransactionCodes .Select(tc => new SelectListItem { Value = tc.Id.ToString(), Text = tc.Code, Disabled = !tc.IsActive }).ToList(); return View(viewModel); } // Check if selected transaction code is valid (active) var selectedCode = _dbContext.TransactionCodes.Find(viewModel.SelectedTransactionCodeId); if (selectedCode == null || !selectedCode.IsActive) { ModelState.AddModelError("SelectedTransactionCodeId", "This transaction code is no longer available."); viewModel.TransactionCodeOptions = _dbContext.TransactionCodes .Select(tc => new SelectListItem { Value = tc.Id.ToString(), Text = tc.Code, Disabled = !tc.IsActive }).ToList(); return View(viewModel); } // Update the File entity and save changes var file = _dbContext.Files.Find(viewModel.Id); file.FileNumber = viewModel.FileNumber; file.TransactionCodeId = viewModel.SelectedTransactionCodeId; _dbContext.SaveChanges(); return RedirectToAction("Index"); }
This approach ensures your dropdown has disabled items that respect your business rules, and includes server-side validation to prevent invalid selections.
内容的提问来源于stack exchange,提问作者Kevin

