简体   繁体   English

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

[英]What is good approach to validate http request in .NET Core 3.1 API's?

I am new to building API's.我是构建 API 的新手。 My project contains three typical layers: controllers, services responsible for business logic, and repositories which are accessing data.我的项目包含三个典型层:控制器、负责业务逻辑的服务和访问数据的存储库。 Every request coming to my controllers have to go through some validation process before a specific action is performed.在执行特定操作之前,向我的控制器发出的每个请求都必须通过一些验证过程到达 go。 For an example, please inspect the code below:例如,请检查以下代码:

[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
            });
    }
}

This is one of my controller methods.这是我的 controller 方法之一。 Before the ticket is saved to database, it has to pass few checks.在将票证保存到数据库之前,它必须通过一些检查。 The owner of the ticket must exist, if not i return user not found etc. The problem is I do not really like this way of validating requests.票的所有者必须存在,否则我返回未找到用户等。问题是我不太喜欢这种验证请求的方式。 The method is messy, and not very readable.该方法很混乱,而且可读性不强。 I would like to know what is a good approach to validate requests, and react properly if something wents wrong (for example return "UserNotFoundErrorMessage" if there is no user in a database, etc. single catch block doesn't solve my problem. I wouldn't also like to have multiple catch blocks there, it's also messy i think. Am i wrong?) I wonder does the attached snippet violate some clean code rules or not?我想知道什么是验证请求的好方法,并在出现问题时做出正确反应(例如,如果数据库中没有用户,则返回“UserNotFoundErrorMessage”等。单个 catch 块不能解决我的问题。我也不希望在那里有多个 catch 块,我认为这也很乱。我错了吗?)我想知道附加的代码片段是否违反了一些干净的代码规则? How the code should look like?代码应该是什么样子? What I am doing wrong?我做错了什么?

All of this logic should be shuffled into your business layer, ie your services.所有这些逻辑都应该洗牌到您的业务层,即您的服务中。 The service methods, then, should return a "result" class, which is basically just a way of sending multiple bits of information back as the return, ie success/fail status, errors, if any, the actual result in the case of a query or something, etc. Then, you can simply switch on the error and respond accordingly.那么,服务方法应该返回一个“结果”class,这基本上只是一种将多位信息作为返回发送回来的方式,即成功/失败状态、错误(如果有)、实际结果查询或其他东西等。然后,您可以简单地打开错误并做出相应的响应。

As far as the catches go, especially the main one that simply returns a 500, use a global exception handler.至于捕获 go,尤其是仅返回 500 的主要捕获,使用全局异常处理程序。 Let the error bubble up from the action and rely on the global handler to return an appropriate response.让错误从操作中冒出来,并依靠全局处理程序返回适当的响应。

Like others have already pointed out, this does not seem half bad.就像其他人已经指出的那样,这似乎还不错。

I can tell you as much that we have snippets of code that are 10 times the size of this.我可以告诉你,我们的代码片段是这个大小的 10 倍。 Tbh, this seems like small part compared to some modules i've seen in my company's codebase. Tbh,与我在公司代码库中看到的一些模块相比,这似乎只是一小部分。

That being said, you could move a bit more logic away from the controller, and to other layers.话虽如此,您可以将更多逻辑从 controller 移到其他层。 For example, when getting a user by its Id, you can also throw a not found exception from your serviceclass if an user by that id does not exist.例如,当通过其 ID 获取用户时,如果该 ID 的用户不存在,您还可以从您的服务类中抛出未找到的异常。 you have now stuffed everything into a controller, whilst it feels like this is more the resposibility of the service.你现在已经把所有东西都塞进了 controller,虽然感觉这更像是服务的责任。

Another thing you could do is perhaps use middleware:您可以做的另一件事可能是使用中间件:

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

You can create validation pipelines for your response.您可以为您的响应创建验证管道。

I've also tried working with a validation pattern.我也尝试过使用验证模式。 In this case i would create some rules for checks, and applied these rules to stuff to validate.在这种情况下,我会创建一些检查规则,并将这些规则应用于要验证的内容。 I then had a validator object that would take all the rules an prompt an appropriate output.然后我有一个验证器 object,它将所有规则提示一个适当的 output。 This made the code cleaner and resuse better, however added some complexity and i ended up not using it.这使代码更清晰,更好地重用,但是增加了一些复杂性,我最终没有使用它。 It was different than the rest of the codebase and therefore foreign to colleagues, and thus i had good argument not to use it.它与代码库的 rest 不同,因此对同事来说是陌生的,因此我有充分的理由不使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 .Net Core 3.1 的 POST 请求和 Power Automate 的 HTTP 请求 - POST Request using .Net Core 3.1 and HTTP Request of Power Automate .Net Core 3.1 - HTTP 请求 - 分别发送标头和正文 - .Net Core 3.1 - HTTP request - Send header and body separately 将包含带有连字符的 Header 属性的请求绑定到 .Net Core 3.1 API - Bind request containing Header property with Hyphens to .Net Core 3.1 API 如何验证 asp.net 核心 3.0 web api 的获取请求中的参数? - How to Validate parameter in asp.net core 3.0 web api's get request? .net 核心 3.1 中 [RoutePrefix("api/{controller})] 的替代方案是什么? - What is alternate for [RoutePrefix("api/{controller})] in .net core 3.1? .net core 3.1 中 RequestCookieCollection 和 ResponseCookies 的替代方案是什么? - what's the alternative of RequestCookieCollection and ResponseCookies in .net core 3.1? HTTP Post 方法的正确结构是什么? ASP.NET Core Web API - What's the correct structure for a HTTP Post method? ASP.NET Core Web API 在 .net core 中通过 http 发出 Grpc 请求时会产生以下异常。 我正在使用 .net 核心 3.1 - When making Grpc request over http in .net core creates following exception. I am using .net core 3.1 asp.net core 3.1 上的 Json 请求 - Json request on asp.net core 3.1 .NET Core 3.1 是否支持 ReuseScope.Request? - Is ReuseScope.Request supported on .NET Core 3.1?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM