ASP.NET Core Razor中如何复用通用页面至多个特定页面
解决方案:复用Razor页面模型实现多CSV数据管理
一、重构通用基类页面模型
把CSV操作、页面逻辑抽成抽象基类,让具体页面模型继承复用,避免重复代码:
public abstract class BaseCsvDataModel : PageModel { // 子类需实现的配置项 protected abstract string PageTitle { get; } protected abstract string CsvFilePath { get; } // 视图绑定数据 public string CurrentTitle { get; set; } public List<IdNameData> DataList { get; set; } = new(); [BindProperty] public IdNameData NewItem { get; set; } = new(); public void OnGet() { CurrentTitle = PageTitle; DataList = ReadCsvData(); } public IActionResult OnPostInsert() { if (!ModelState.IsValid) { DataList = ReadCsvData(); CurrentTitle = PageTitle; return Page(); } // 生成新ID(空列表时默认ID为1) var newId = DataList.Any() ? DataList.Max(x => x.Id) + 1 : 1; NewItem.Id = newId; AppendToCsv(NewItem); return RedirectToPage(); } public IActionResult OnPostDelete(int id) { var data = ReadCsvData(); data.RemoveAll(x => x.Id == id); WriteCsvData(data); return RedirectToPage(); } // 通用CSV读取方法 private List<IdNameData> ReadCsvData() { var data = new List<IdNameData>(); if (!File.Exists(CsvFilePath)) return data; var lines = File.ReadAllLines(CsvFilePath); foreach (var line in lines.Skip(1)) // 跳过表头行 { var parts = line.Split(','); if (parts.Length == 2 && int.TryParse(parts[0], out var id)) { data.Add(new IdNameData { Id = id, Name = parts[1] }); } } return data; } // 追加数据到CSV private void AppendToCsv(IdNameData item) { lock (_lockObj) // 多场景下加锁避免并发冲突 { var line = $"{item.Id},{item.Name}"; if (!File.Exists(CsvFilePath)) { File.WriteAllText(CsvFilePath, "Id,Name\n"); } File.AppendAllText(CsvFilePath, line + "\n"); } } // 覆盖写入全部数据 private void WriteCsvData(List<IdNameData> data) { lock (_lockObj) { var lines = new List<string> { "Id,Name" }; lines.AddRange(data.Select(x => $"{x.Id},{x.Name}")); File.WriteAllLines(CsvFilePath, lines); } } private static readonly object _lockObj = new object(); } // 通用Id-Name数据模型 public class IdNameData { public int Id { get; set; } public string Name { get; set; } = string.Empty; }
二、创建具体页面模型
比如针对data1.csv的页面模型,只需配置标题和文件路径:
public class Data1Model : BaseCsvDataModel { private readonly IWebHostEnvironment _env; public Data1Model(IWebHostEnvironment env) { _env = env; } protected override string PageTitle => "数据列表1"; protected override string CsvFilePath => Path.Combine(_env.WebRootPath, "data1.csv"); }
三、通用视图组件(Partial View)
创建_CsvDataManager.cshtml作为通用视图,避免重复编写表单和表格代码:
@model BaseCsvDataModel <h1>@Model.CurrentTitle</h1> <!-- 插入表单 --> <form method="post" asp-page-handler="Insert"> <div> <label>名称:</label> <input asp-for="NewItem.Name" required /> <span asp-validation-for="NewItem.Name" class="text-danger"></span> </div> <button type="submit">添加</button> </form> <!-- 数据表格 --> <table border="1" cellpadding="8"> <thead> <tr> <th>ID</th> <th>名称</th> <th>操作</th> </tr> </thead> <tbody> @foreach (var item in Model.DataList) { <tr> <td>@item.Id</td> <td>@item.Name</td> <td> <form method="post" asp-page-handler="Delete"> <input type="hidden" name="id" value="@item.Id" /> <button type="submit">删除</button> </form> </td> </tr> } </tbody> </table>
四、具体页面视图(Data1.cshtml)
直接引用通用Partial View即可:
@page @model Data1Model @{ ViewData["Title"] = Model.CurrentTitle; } <partial name="_CsvDataManager" model="Model" />
五、解决OnGet无渲染问题的排查点
- 确认具体页面模型正确继承
BaseCsvDataModel,且基类OnGet方法未被重写覆盖。 - 检查CSV文件路径是否正确:用
IWebHostEnvironment获取根目录,避免硬编码路径错误。 - 查看Visual Studio输出窗口,确认页面无编译错误;打开浏览器控制台,排查前端渲染报错。
- 验证CSV文件是否存在,且当前程序有读写权限(开发环境下wwwroot目录默认具备权限)。
内容的提问来源于stack exchange,提问作者Douar Gwenn
相关产品推荐
相关产品推荐

