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

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无渲染问题的排查点

  1. 确认具体页面模型正确继承BaseCsvDataModel,且基类OnGet方法未被重写覆盖。
  2. 检查CSV文件路径是否正确:用IWebHostEnvironment获取根目录,避免硬编码路径错误。
  3. 查看Visual Studio输出窗口,确认页面无编译错误;打开浏览器控制台,排查前端渲染报错。
  4. 验证CSV文件是否存在,且当前程序有读写权限(开发环境下wwwroot目录默认具备权限)。

内容的提问来源于stack exchange,提问作者Douar Gwenn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 07:50:08