ASP.NET Core中复用Edit/New视图cshtml代码的最佳方案
首先明确:90%的常规CRUD场景下,最高效的方案不是View Component,而是强类型分部视图(Partial View),配合ASP.NET Core增强的标签助手、编辑器模板能力,代码量比.NET Framework时代的实现少一半以上。
各方案适用场景对比
优先选:强类型分部视图
这是投入产出比最高的方案,没有额外开发成本。New和Edit视图的核心差异极小:通常只是提交地址不同、编辑页多一个Id隐藏域、按钮文案不同,完全可以把重复的表单代码抽成公共分部视图,在分部视图内部通过模型属性做极少量的差异化判断即可。
示例实现:- 新建公共分部视图,比如
Views/Shared/Partials/_ProductForm.cshtml,绑定两个视图共用的Edit/Create ViewModel:
@model ProductEditViewModel <form asp-action="@(Model.Id == default ? "Create" : "Edit")" method="post" class="mt-3"> @* 以下是两个页面完全重复的表单项、验证逻辑,全放在公共区域 *@ <div class="mb-3"> <label asp-for="ProductName" class="form-label"></label> <input asp-for="ProductName" class="form-control" /> <span asp-validation-for="ProductName" class="text-danger"></span> </div> <div class="mb-3"> <label asp-for="Price" class="form-label"></label> <input asp-for="Price" class="form-control" /> <span asp-validation-for="Price" class="text-danger"></span> </div> @* 仅编辑页需要渲染的内容:隐藏Id、并发令牌、更新时间提示等 *@ @if (Model.Id != default) { <input type="hidden" asp-for="Id" /> <input type="hidden" asp-for="ConcurrencyStamp" /> <div class="alert alert-secondary">最后更新时间:@Model.LastUpdateTime.ToString("yyyy-MM-dd HH:mm")</div> } <button type="submit" class="btn btn-primary"> @(Model.Id == default ? "确认新建" : "保存修改") </button> </form>- 原New.cshtml、Edit.cshtml只保留页面独有内容,一行代码引入公共表单即可:
@* New.cshtml *@ @model ProductEditViewModel <h1>新建商品</h1> <partial name="_ProductForm" model="Model" />@* Edit.cshtml *@ @model ProductEditViewModel <h1>编辑商品</h1> <partial name="_ProductForm" model="Model" />ASP.NET Core原生的
<partial>标签助手支持强类型传模,不需要像.NET Framework时代那样手动处理ViewData传值、视图上下文切换的问题,渲染性能和直接写在页面里几乎没有差异。- 新建公共分部视图,比如
次选:编辑器模板(Editor Template)
如果你要复用的是某一类特定数据类型的输入逻辑(比如枚举选择器、地址组件、富文本编辑器),直接把对应视图放到Views/Shared/EditorTemplates/[类型名].cshtml路径下,所有页面调用Html.EditorFor(m=>m.对应属性)时会自动渲染复用模板,连分部视图名都不需要手动指定,还能自动嵌套支持子属性验证,适合细粒度的表单项复用。这个特性在.NET Framework中就存在,Core里做了性能优化和标签助手适配,体验更好。不推荐常规场景用View Component
View Component的定位是「需要独立执行业务逻辑的可复用区块」,比如页头购物车、动态权限菜单、关联数据列表——这类组件需要自己走依赖注入、查数据库、执行独立业务逻辑的流程,才适合用View Component。如果只是复用静态表单标记,用View Component需要额外编写组件类、Invoke方法,平白增加至少3倍的代码量,完全是过度设计。
ASP.NET Core 特有的进阶复用方案
如果你的复用需求不止于单个项目,还有两个Core独有的高效方案:
- 自定义标签助手:把常用的表单项(带label、输入框、验证提示的表单组)封装成标签助手,比如直接写
<form-input asp-for="ProductName" />就能生成整套表单元素,比写分部视图更简洁,支持全局统一调整样式。 - Razor类库(RCL):把公共分部视图、标签助手、编辑器模板统一打包成独立的Razor类库,多个业务项目直接引用就能用,不需要复制任何cshtml代码,支持按需覆盖视图,是跨项目视图复用的最优方案。
注意:不要为了严格遵循DRY硬把两个页面差异极大的逻辑塞进公共分部,比如编辑页独有的操作历史、关联数据审核区块,直接留在Edit视图里即可,避免公共分部里堆砌大量分支判断,反而提升维护成本。
内容的提问来源于stack exchange,提问作者RobertDev22

