. Net WebApi naming convention

Posted by renzaho on Wed, 19 Jan 2022 19:34:39 +0100

HTTP Service development guide of elephant doctor company

1. Webapi interface implementation specification

1.1 several implementations of get method

1.1.1 basic realization

    // GET: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63

    /// <summary>
    ///Get specific products
    /// </summary>
    ///< param name = "Id" > Product ID < / param >
    /// <returns></returns>
    [Route("~/api/v1/Products/{id}")]
    [ResponseType(typeof(ProductOutput))]
    public IHttpActionResult GetProduct(Guid id)
    {
        var result = productService.GetProductById(id);
        return Ok(result);
    }

standard:

  • First line: take a specific URL example as the first line. The URL starts with the HTTP method name, which is capitalized, followed by colon + space + URL. It is required to use the URL for debugging at run time to enter the method body;
  • Note line: it is recommended to obtain XX resources or XX resources that meet XX conditions as a description, for example: obtain products under promotion;
  • Routing: this part is optional when the default routing rules are met. The parameter part, as the identification of this resource, does not need to add the resource name as a prefix. For example, instead of using productId, use id directly. Only when other resource IDS appear in the URL, the other resource id needs to be prefixed with the qualified resource name. The Route attribute always appears above the interface method or ResponseType attribute.
  • Response type: when the interface method returns the IHttpActionResult type, Swagger cannot deduce the specific response type. It must be declared with the ResponseType in order to generate the correct Swagger metadata. The ResponseType attribute always appears above the interface method (or SwaggerResponse attribute).
  • Interface method declaration: Method naming always uses complete semantics to clearly describe the specific functions of this method. Swagger generates the operationId in the metadata according to the method name, and the operationId cannot be duplicated. Therefore, we must ensure the accuracy of semantic expression to avoid repetition. However, in this example, using GetProduct or GetProducts to return products with a specific id or all products is an allowed naming convention and does not need to be specifically named GetProductById or GetAllProducts.
  • Return result intermediate variable: it is recommended to define the intermediate variable var result to obtain the return result value for debugging, and make the parameters in the final result return code return Ok() more concise.

1.1.2 implementation of return with multiple status codes

    // GET: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63

    /// <summary>
    ///Get specific products
    /// </summary>
    ///< param name = "Id" > Product ID < / param >
    /// <returns></returns>
    [Route("~/api/v1/Products/{id}")]
    [ResponseType(typeof(ProductOuput))]
    [SwaggerResponse(HttpStatusCode.NotFound)]
    public IHttpActionResult GetProduct(Guid id)
    {
        var result = productService.GetProductById(id);
        if (result == null)
        {
            return NotFound();
        }

        return Ok(result);
    }

standard:

  • SwaggerResponse: the SwaggerResponse attribute is used to describe the status codes other than 200 returned by the interface, which will generate the corresponding Description in the metadata. It is recommended that SwaggerResponse always appear on the interface method. The input parameters include StatusCode, Description and Type. When the return meaning cannot be inferred by using StatusCode, the Description must be used to indicate the Description; When the responder has return content, the return Type must be marked with Type.
  • Using the response configuration section of XML Documentation can also achieve a similar effect to SwaggerResponse, as shown below. It should be noted that SwaggerResponse has higher priority in case of conflict between the two.

    /// <response code="404">Not Found</response>
    

1.1.3 implementation of returning set results

    // GET: api/v1/Products

    /// <summary>
    ///Get all products
    /// </summary>
    ///< returns > Product Collection < / returns >
    [Route("~/api/v1/Products")]
    public IEnumerable<ProductOutput> GetProducts()
    {
        var result = productService.GetProducts();
        return result;
    }

standard:

  • When a set is returned as a result, if the result set is empty, you do not need to return 404, but only an empty result set. Therefore, when no other non-200 returns are required, the return type of the method can be a collection type instead of IHttpActionResult.

1.1.4 implementation of returning paging collection results

    // GET: api/v1/Products?Pager.PageIndex=1&Pager.PageSize=10

    /// <summary>
    ///Get a paged list of all products
    /// </summary>
    ///< returns > Product pagination list < / returns >
    [Route("~/api/v1/Products")]
    public IPagedList<ProductOutput> GetPagedProducts([FromUri] Pager pager)
    {
        var result = productService.GetPagedProducts(pager);
        return result;
    }

standard:

  • Pager, filter, sorter, etc. should be passed through Query String. In this example, the parameters PageIndex and PageSize in the Query String must use the pager prefix to bind to the method parameter pager.
  • Pager, IPagedList, SortBy and other types are implemented by elephant The core library provides. For how to reference the enterprise core database, please refer to the development and release instructions of elephant doctor's core database.

1.2 several implementations of post method

1.2.1 basic implementation of creating resources

    // POST: api/v1/Products

    /// <summary>
    ///Create product
    /// </summary>
    ///< param name = "product" > Product < / param >
    /// <returns></returns>
    [Route("~/api/v1/Products")]
    [SwaggerResponseRemoveDefaults]
    [SwaggerResponse(HttpStatusCode.BadRequest)]
    [SwaggerResponse(HttpStatusCode.Created, Type = typeof(ProductOutput))]
    public IHttpActionResult PostProduct([FromBody]ProductInput product)
    {
        if (ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var result = productService.CreateProduct(product);

        return CreatedAtRoute("DefaultApi", new { id = product.Id }, result);
    }

standard:

  • When the resource is created successfully, 201 Created should be returned instead of 200 OK. At the same time, you need to return the URL corresponding to the created new resource and the content of the resource in the location section of HTTP response headers.
  • SwaggerResponseRemoveDefaults: you can cancel the default in the generated metadata and return the status code 200. In this example, 201 will become the new default return status code and be displayed in the Swagger document.
  • When there is a DTO as an input, it is necessary to verify the validity of the DTO model. Use ModelState Isvalid performs verification, and returns 400 and ModelState when verification fails. The ModelState contains the specific reason why the model verification failed.
  • Using CreatedAtRoute, you can apply an existing route. In this example, a default route named DefaultApi is used. This default route is usually defined in webapiconfig CS file. But more often, an existing custom route is used. At this time, this route needs to be declared as a named route. For example, the route of the GET method in the previous example can be rewritten as follows to make it a named route, and use the name GetProductById (instead of DefaultApi in this example). This route is the URL used to create a new resource. In this example, new {id = parameter ID in product. ID} will replace the parameter ID in the route, and result will be returned as the Content in the Content.

    [Route("~/api/v1/Products/{id}", Name = "GetProductById")]
    
  • In this example, the Input parameter product of the method should be a DTO as Input, and the result variable should be a DTO as Output. Related DTOs are named with Input or Output as the suffix. Suffixes are not limited to Input and Output, but also Create or Update can be used to further distinguish purposes.

1.2.2 implementation of other non idempotent operations

    // POST: api/v1/Products/Last/Remove

    /// <summary>
    ///Delete last product
    /// </summary>
    /// <returns></returns>
    [Route("~/api/v1/Products/Last/Remove")]
    [SwaggerResponseRemoveDefaults]
    [SwaggerResponse(HttpStatusCode.NotFound)]
    [SwaggerResponse(HttpStatusCode.NoContent)]
    public IHttpActionResult RemoveLastProduct()
    {
        var result = productService.RemoveLastProduct();
        if (!result)
        {
            return NotFound();
        }

        return StatusCode(HttpStatusCode.NoContent);
    }

standard:

  • In this example, the operation of deleting the last product satisfies non idempotent, that is, multiple operations may DELETE multiple different products, resulting in different system states. For operations that are semantically possible to use PUT or DELETE, if they meet non idempotent, the POST method should be used.
  • When the operation represented by the method is no longer used to create resources, the operation noun itself is used to replace the naming of the Post method. Therefore, the method in this example is not PostRemoveLastProduct.
  • When a method name other than the Post prefix is used, the Web API defaults to the Post method according to the naming convention. Therefore, the HttpPost feature is not required in this example (other HTTP methods need to be explicitly declared).
  • 204 NoContent should be returned when the operation does not contain a return value.

1.3 several implementations of put method

1.3.1 basic implementation of update resources

    // PUT: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63

    /// <summary>
    ///Update product
    /// </summary>
    ///< param name = "Id" > Product ID < / param >
    ///< param name = "product" > Product < / param >
    /// <returns></returns>
    [Route("~/api/v1/Products/{id}")]
    [SwaggerResponseRemoveDefaults]
    [SwaggerResponse(HttpStatusCode.NotFound)]
    [SwaggerResponse(HttpStatusCode.NoContent)]
    public IHttpActionResult PutProduct(Guid id, [FromBody]ProductInput product)
    {
        if (ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var result = productService.GetProductById(id);
        if (result == null)
        {
            return NotFound();
        }

        productService.UpdateProduct(id, product);

        return StatusCode(HttpStatusCode.NoContent);
    }

standard:

  • According to the official definition, if the use of PUT means that the resource does not exist or does not exist, a new resource is created; Or the resource exists, and the original resource is completely replaced with a new resource. In either case, the results of the system state obtained after multiple operations are completely consistent, so it conforms to idempotence. In this example, instead of creating a new resource because the resource does not exist, 404 NotFound is returned, but idempotency is still not violated. The specific strategy should be determined according to the needs of the actual application scenario. If a new resource is created, 201 Created should be returned.
  • The identification of the resource is passed independently through the parameter id in the method, and the ProductInput does not contain the id attribute. Before updating, you need to judge whether the resource corresponding to the id exists, and then carry out further operations.

1.3.2 implementation of other idempotent operations

    // PUT: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63/Disable

    /// <summary>
    ///Off shelf products
    /// </summary>
    ///< param name = "Id" > Product ID < / param >
    /// <returns></returns>
    [HttpPut]
    [Route("~/api/v1/Products/{id}/Disable")]
    [SwaggerResponseRemoveDefaults]
    [SwaggerResponse(HttpStatusCode.NotFound)]
    [SwaggerResponse(HttpStatusCode.NoContent)]
    public IHttpActionResult DisableProduct(Guid id)
    {
        var result = productService.GetProductById(id);
        if (result == null)
        {
            return NotFound();
        }

        productService.DisableProduct(id);

        return StatusCode(HttpStatusCode.NoContent);
    }

standard:

  • When the operation represented by the method is no longer used to update resources, use the operation noun itself instead of Put to name the method. Since the naming convention determines that the default HTTP method is POST, the HttpPut attribute needs to be explicitly identified here.
  • Since the results of removing the same product from the shelf for many times are consistent, the operation of this example conforms to idempotency.

1.4 several implementations of delete method

1.4.1 basic implementation of deleting resources

    // DELETE: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63

    /// <summary>
    ///Delete product
    /// </summary>
    ///< param name = "Id" > Product ID < / param >
    /// <returns></returns>
    [Route("~/api/v1/Products/{id}")]
    [SwaggerResponseRemoveDefaults]
    [SwaggerResponse(HttpStatusCode.NotFound)]
    [SwaggerResponse(HttpStatusCode.NoContent)]
    public IHttpActionResult DeleteProduct(Guid id)
    {
        var result = productService.GetProductById(id);
        if (result == null)
        {
            return NotFound();
        }

        productService.DeleteProduct(id);

        return StatusCode(HttpStatusCode.NoContent);
    }

standard:

  • The DELETE method should satisfy idempotency. In this example, multiple deletion operations will change the system state to the product deleted state. Therefore, although there are multiple possibilities for the return of the status code, the system state is always the same.

1.5 definition of idempotency

Idempotency should focus on sending multiple repeated operations and whether the results of the system state are always consistent, rather than whether the interface returns are consistent. System status here mainly refers to business status, but does not include status changes generated in addition to business, such as logs, statistics, etc. For idempotent write operations, POST and DELETE methods can be used; Otherwise, even if it is an update or DELETE operation semantically, the POST method should be used to comply with the HTTP protocol and ensure that the results of some external behaviors based on the protocol meet the expectations.

1.5 status return code

  • In the above example, if no content is returned after the operation is successful, 200 OK and 204 NoContent are common in most cases. However, for the sake of programming consistency, 204 NoContent return is used uniformly.
  • When the operation fails due to violation of business rule constraints, 409 Conflict should be returned.
 
Turn https://www.cnblogs.com/PengQuanfeng/p/9882583.html

Topics: .NET