在.NET Core 3.1 API中验证http请求的好方法是什么?

问题描述 投票:0回答:2

我是构建API的新手。我的项目包含三个典型的层:控制器,负责业务逻辑的服务以及正在访问数据的存储库。在执行特定操作之前,到达我的控制器的每个请求都必须经过一些验证过程。例如,请检查以下代码:

[HttpPost]
public async Task<ActionResult<TicketDTO>> CreateTicketAsync([FromBody] CreateTicketDTO ticket)
{
    try
    {
        if (ticket.Events == null)
        {
            return BadRequest(new {Message = _localizer["LackOfEventsErrorMessage"].Value});
        }

        var user = await _userService.GetUserByIdAsync(ticket.UserId);

        if (user == null)
        {
            return NotFound(new { Message = _localizer["UserNotFoundErrorMessage", ticket.UserId].Value });
        }

        var invalidTicket = await _ticketService.CheckHasUserPlayedAnyOfGamesBeforeAsync(ticket);

        if (invalidTicket)
        {
            return BadRequest(new { Message = _localizer["EventsRepeatedByUserErrorMessage"].Value });
        }

        var createdTicket = await _ticketService.AddTicketAsync(ticket);

        if (createdTicket == null)
        {
            return BadRequest(new { Message = _localizer["TicketNotCreatedErrorMessage"].Value });
        }

        return CreatedAtAction(nameof(GetTicketById), new {ticketId = createdTicket.TicketId}, createdTicket);
    }
    catch (Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError,
            new
            {
                Message = ex.InnerException != null
                    ? $"{ex.Message} {ex.InnerException.Message}"
                    : ex.Message
            });
    }
}

这是我的控制器方法之一。在将票证保存到数据库之前,它必须通过几次检查。票证的所有者必须存在,否则,我将找不到返回的用户等。问题是我真的不喜欢这种验证请求的方式。该方法比较混乱,而且可读性很差。我想知道什么是验证请求的好方法,并在出现问题时正确做出反应(例如,如果数据库中没有用户,则返回“ UserNotFoundErrorMessage”,等等。单个catch块不能解决我的问题。)也不希望在那里有多个捕获块,我认为这也很混乱。我错了吗?)我想知道所附的代码片段是否违反了一些干净的代码规则?代码看起来如何?我做错了什么?

c# asp.net-core controller coding-style
2个回答
0
投票

所有这些逻辑都应该混入您的业务层,即您的服务中。然后,服务方法应该返回一个“结果”类,这基本上只是一种将信息的多个位作为返回发送回去的方法,即成功/失败状态,错误(如果有),实际结果(如果有)。查询等。然后,您只需打开错误并做出相应响应即可。

就捕获而言,尤其是仅返回500的主要捕获,请使用全局异常处理程序。让错误从操作中冒出来,并依靠全局处理程序返回适当的响应。


0
投票

[就像其他人已经指出的那样,这似乎并不坏。

我可以告诉您很多,我们的代码片段是此代码片段的10倍。待定,与我公司代码库中的某些模块相比,这似乎只是很小的一部分。

话虽如此,您可以将更多逻辑从控制器移到其他层。例如,当通过其ID获取用户时,如果不存在具有该ID的用户,则还可以从服务类中抛出未找到的异常。您现在已经将所有内容填充到控制器中,而感觉这更像是服务的可重复性。

您可能要做的另一件事是使用中间件:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1

您可以为您的响应创建验证管道。

我也尝试过使用验证模式。在这种情况下,我将创建一些检查规则,并将这些规则应用于东西以进行验证。然后,我有了一个验证器对象,该对象将采用所有规则并提示适当的输出。这使代码更整洁,重用更好,但是增加了一些复杂性,最终我没有使用它。它与代码库的其余部分不同,因此对同事来说是陌生的,因此我有很好的理由不使用它。

© www.soinside.com 2019 - 2024. All rights reserved.