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

Razor视图向Controller传递数据的最佳实践及相关问题咨询

Razor视图向Controller传递数据的最佳实践咨询

现有代码

视图代码

<form method="post" asp-controller="Comments" asp-action="CreateComment">
     @Html.AntiForgeryToken()
     <input type="hidden" name="relatedPostId" value="@Model.ID" />
     <input type="hidden" name="username" value="@User.FindFirst(ClaimTypes.Name)?.Value" />
     <div class="form-group mt-2">
         <label for="note">Add a new comment:</label>
         <textarea class="form-control" name="commentContent" rows="2" required style="resize:none"></textarea>
     </div>
     <button type="submit" class="btn btn-success mt-2">Add</button>
</form>

Controller Action代码

[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateComment(int relatedPostId, string username, 
string commentContent)
{
  (...)
}

问题解答

1. 是否应该创建CreateCommentRequest模型接收参数?

建议创建专门的请求模型,核心原因如下:

  • 便捷的参数校验:可以在模型属性上添加[Required]、[MaxLength]等数据注解,结合ModelState.IsValid统一完成校验,比逐个校验独立参数更高效。
  • 代码更整洁易维护:Action方法参数会更简洁,后续新增参数时只需在模型中添加属性,无需修改Action的参数列表。
  • 扩展性更强:统一的模型结构能更好适配后续业务需求变化。

视图已有其他模型时的使用方式

如果当前视图绑定了其他主模型(比如PostViewModel),可以通过以下两种方式处理:

  • 方式一:使用复合ViewModel
    创建包含主模型和请求模型的复合ViewModel:

    public class PostDetailViewModel
    {
        public Post Post { get; set; } // 原视图绑定的主模型
        public CreateCommentRequest CommentRequest { get; set; } = new();
    }
    

    视图中通过asp-for标签辅助器绑定请求模型的属性:

    <form method="post" asp-controller="Comments" asp-action="CreateComment">
        @Html.AntiForgeryToken()
        <input type="hidden" asp-for="CommentRequest.RelatedPostId" value="@Model.Post.ID" />
        <div class="form-group mt-2">
            <label for="note">Add a new comment:</label>
            <textarea class="form-control" asp-for="CommentRequest.CommentContent" rows="2" required style="resize:none"></textarea>
        </div>
        <button type="submit" class="btn btn-success mt-2">Add</button>
    </form>
    

    Controller直接接收请求模型:

    [HttpPost]
    [Authorize]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> CreateComment(CreateCommentRequest request)
    {
        if (!ModelState.IsValid)
        {
            // 处理校验失败逻辑
            return View();
        }
        // 执行业务逻辑
    }
    
  • 方式二:使用局部视图
    将评论表单封装为局部视图,直接把CreateCommentRequest作为局部视图的模型:

    <!-- _CreateCommentPartial.cshtml -->
    @model CreateCommentRequest
    <form method="post" asp-controller="Comments" asp-action="CreateComment">
        @Html.AntiForgeryToken()
        <input type="hidden" asp-for="RelatedPostId" />
        <div class="form-group mt-2">
            <label for="note">Add a new comment:</label>
            <textarea class="form-control" asp-for="CommentContent" rows="2" required style="resize:none"></textarea>
        </div>
        <button type="submit" class="btn btn-success mt-2">Add</button>
    </form>
    

    在主视图中渲染局部视图时传入参数:

    @await Html.PartialAsync("_CreateCommentPartial", new CreateCommentRequest { RelatedPostId = Model.ID })
    

2. 视图中从Claims获取值的方式是否合理?

不合理,存在明显安全风险:

  • 前端的隐藏输入框可以被用户随意篡改,攻击者可以修改username字段的值,冒充其他用户提交评论,破坏数据的真实性和安全性。

正确的做法是在Controller中从Claims获取用户信息,同时移除视图中的username隐藏字段:

[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateComment(CreateCommentRequest request)
{
    var username = User.FindFirst(ClaimTypes.Name)?.Value;
    if (string.IsNullOrEmpty(username))
    {
        // 处理用户未登录或无合法用户名的情况
        return Unauthorized();
    }
    // 使用username执行业务逻辑
}

这种方式下,用户信息是从服务器端验证过的Claims中获取,无法被前端篡改,安全性更有保障。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:07:49