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

ASP.NET实现仅编辑每个车牌对应最新RoadRecord记录的方法

实现方案

需求为对RoadRecord行驶记录表做操作权限限制:仅允许用户对每个车牌号(LicencePlate)对应的最新一条记录执行编辑、删除操作,示例数据规则如下:

DateLicencePlate可编辑状态
08.19AAA-111是
08.17AAA-111否
08.16CCC-222是

你手写的SQL查询逻辑可直接通过Entity Framework转换为业务代码,落地分三层实现,必须加后端校验避免用户通过手动拼接URL越权:

1. 数据查询层:标记记录可编辑状态

不要直接将RoadRecord实体集合传入视图,给列表视图模型新增bool CanEdit字段,通过LINQ查询直接计算每条记录的编辑权限,和你手写的SQL逻辑完全等价:

// 数据库上下文注入后执行查询
// 第一步:分组查询每个车牌对应的最新记录标识
var latestRecordMark = _context.RoadRecords
    .GroupBy(r => r.LicencePlate)
    .Select(g => new 
    { 
        LicencePlate = g.Key, 
        // 若同一车牌同一天存在多条记录,优先取最大Id匹配,避免日期重复导致权限判断错误
        AllowEditId = g.OrderByDescending(r => r.Date).ThenByDescending(r => r.Id).First().Id
    });

// 第二步:关联全量记录,赋值可编辑标识
var pageData = from record in _context.RoadRecords
               join mark in latestRecordMark 
               on new { record.LicencePlate, record.Id } equals new { mark.LicencePlate, Id = mark.AllowEditId }
               into tempMatch
               from matchRes in tempMatch.DefaultIfEmpty()
               select new RoadRecordListVM
               {
                   Id = record.Id,
                   Date = record.Date,
                   LicencePlate = record.LicencePlateNavigation.LicencePlate,
                   UserName = record.User.Name,
                   Location = record.Location,
                   Mileage = record.Mileage,
                   Fueling = record.Fueling,
                   Note = record.Note,
                   CanEdit = matchRes != null
               };
// 将pageData作为Model传入视图即可

如果偏好使用原生SQL,也可以直接执行你写的查询语句拿到可编辑记录的Id集合,再做全量列表的匹配标记。

2. 视图层:按权限渲染操作按钮

修改现有.cshtml的循环渲染逻辑,仅对标记为可编辑的记录展示编辑、删除入口:

<tbody>
@foreach (var item in Model)
{
    <tr class="click box-shadow" onclick="location.href = '@(Url.Action("Details", "RoadRecords", new { id = item.Id }))'">
        <td>@Html.DisplayFor(modelItem => item.Date)</td>
        <td>@Html.DisplayFor(modelItem => item.LicencePlate)</td>
        <td>@Html.DisplayFor(modelItem => item.UserName)</td>
        <td>@Html.DisplayFor(modelItem => item.Location)</td>
        <td>@Html.DisplayFor(modelItem => item.Mileage)</td>
        <td>@Html.DisplayFor(modelItem => item.Fueling)</td>
        <td>@Html.DisplayFor(modelItem => item.Note)</td>
        <td>
            @if (item.CanEdit)
            {
                <a asp-action="Edit" asp-route-id="@item.Id">Szerkesztés</a> |
                <a asp-action="Delete" asp-route-id="@item.Id">Törlés</a>
            }
            else
            {
                <span class="text-muted">仅最新记录可编辑</span>
            }
        </td>
    </tr>
}
</tbody>

3. 接口层:强制后端权限校验

前端按钮隐藏仅做体验优化,必须在Edit、Delete的POST接口中增加权限校验,拦截越权请求:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, RoadRecord updateModel)
{
    var currentRecord = await _context.RoadRecords.FindAsync(id);
    if (currentRecord == null) return NotFound();

    // 查询当前车牌对应的最新记录Id
    var latestId = await _context.RoadRecords
        .Where(r => r.LicencePlate == currentRecord.LicencePlate)
        .OrderByDescending(r => r.Date)
        .ThenByDescending(r => r.Id)
        .Select(r => r.Id)
        .FirstAsync();

    // 非最新记录直接返回403
    if (latestId != id) return Forbid("仅允许编辑对应车牌的最新行驶记录");

    // 原有编辑保存逻辑保持不变
    // ...
}

Delete接口复用相同校验逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:15:33