Razor Pages使用Html.EditorFor()时Id字段只读需求解决方案问询
Hey there! I totally get where you're coming from—when you're new to Razor Pages, relying on @Html.EditorFor to handle all form rendering feels like a huge time-saver, but those tiny customization needs (like making a field read-only in some views and not others) can throw a wrench in things. Let's fix this Id field issue step by step.
Why Your Previous Attempts Didn't Work
First, let's clear up why [ScaffoldColumn(false)] and [HiddenInput] didn't do what you wanted:
[ScaffoldColumn(false)]tellsEditorForto skip rendering the field entirely. That means your Id won't be included in the form submission, which breaks edit functionality since the app can't identify which book to update.[HiddenInput]generates a hidden field, which keeps the Id value intact for submission but doesn't show it to the user—you wanted it visible but read-only, so this misses the mark.
Fix 1: Manual Field Rendering (Simplest Approach)
Instead of letting EditorFor render every field automatically, split out the Id field and control its rendering manually in each view. This gives you full control over how it behaves in create vs edit scenarios.
For the Create Page (Create.cshtml)
- First, set the default Id value in your PageModel's
OnGetmethod:public IActionResult OnGet() { // Initialize the Book with Id = 0 by default Book = new Book { Id = 0 }; return Page(); } - In your view, replace the full
@Html.EditorFor(model => model.Book)with individual field renderers, and make the Id field read-only:<!-- Render other fields with EditorFor as usual --> <div class="form-group"> <label asp-for="Book.Title" class="control-label"></label> <input asp-for="Book.Title" class="form-control" /> <span asp-validation-for="Book.Title" class="text-danger"></span> </div> <!-- ... repeat for other Book properties ... --> <!-- Custom Id field rendering --> <div class="form-group"> <label asp-for="Book.Id" class="control-label"></label> <input asp-for="Book.Id" readonly class="form-control" /> <span asp-validation-for="Book.Id" class="text-danger"></span> </div>
This will show the Id as 0, prevent users from editing it, and still keep validation intact if you have any rules for Id.
For the Edit Page (Edit.cshtml)
- Your PageModel should already be fetching the existing Book from the database in
OnGet(int id), so the Id will be populated correctly. - In the view, render the Id field with the
readonlyattribute just like in the create page:<!-- Render other fields with EditorFor as usual --> <div class="form-group"> <label asp-for="Book.Title" class="control-label"></label> <input asp-for="Book.Title" class="form-control" /> <span asp-validation-for="Book.Title" class="text-danger"></span> </div> <!-- ... repeat for other Book properties ... --> <!-- Read-only Id field for edit --> <div class="form-group"> <label asp-for="Book.Id" class="control-label"></label> <input asp-for="Book.Id" readonly class="form-control" /> <span asp-validation-for="Book.Id" class="text-danger"></span> </div>
This displays the existing Id value and locks it so users can't modify it during editing.
Fix 2: Using Editor Templates (For Reusability)
If you want to avoid repeating the Id field code across views, you can create a custom editor template for the Id type:
- Create a folder
Views/Shared/EditorTemplatesif it doesn't exist. - Add a new Razor view named
Int32.cshtml(assuming your Id is an integer):@model int? @{ // Check if we're in an edit context (adjust logic based on your page routing) var isEditPage = ViewContext.RouteData.Values["action"].ToString() == "Edit"; } <div class="form-group"> <label asp-for="@Model" class="control-label"></label> @if (isEditPage || ViewData["ForceReadOnly"] != null) { <input asp-for="@Model" readonly class="form-control" /> } else { <input asp-for="@Model" class="form-control" /> } <span asp-validation-for="@Model" class="text-danger"></span> </div> - Now, when you use
@Html.EditorFor(model => model.Book.Id), it will use this template. For the create page, pass a ViewData flag to force read-only:@Html.EditorFor(model => model.Book.Id, new { ForceReadOnly = true })
This is a bit more advanced but great if you have multiple models with Id fields that need the same behavior.
Final Notes
- Always make sure the Id is included in form submissions (even if read-only) so your PageModel can access it for create/edit operations.
- If you don't want to show the Id at all in either view, use a hidden field (
<input asp-for="Book.Id" type="hidden" />) instead of a read-only text box—but this goes against your requirement to have it visible and read-only.
内容的提问来源于stack exchange,提问作者byteman

