简体   繁体   中英

ASP.NET Web API Controller Best Practice - Action Definitions

I'm running into a situation where my HttpGet action in my Web API controller has multiple ways to be called based on parameters specified in the query string.

I need to be able to handle the following GET requests:

 ~/businesses/{businessId}
 ~/businesses?hasOwnProperty={propertyName}
 ~/businesses?latitude={lat}&longitude={long}&hasOwnProperty={propertyName}

Code Sample 1:

[HttpGet]
public HttpResponseMessage Get(string hasOwnProperty, ODataQueryOptions<Core.Models.Entities.Business> query)
{
    var businessesREST = _businessRepo.Gets(hasOwnProperty, query);

    response = Request.CreateResponse(HttpStatusCode.OK, businessesREST);
    response.Headers.Location = new Uri(businessesREST.Href);

    return response;
}

[HttpGet]
public HttpResponseMessage Get(double latitude, double longitude, string hasOwnProperty, ODataQueryOptions<Core.Models.Entities.Business> query)
{
    var businessesREST = _businessRepo.GetsByLatLong(latitude, longitude, hasOwnProperty, query);

    response = Request.CreateResponse(HttpStatusCode.OK, businessesREST);
    response.Headers.Location = new Uri(businessesREST.Href);

    return response;
}

[HttpGet]
public HttpResponseMessage GetBusiness(string businessId, ODataQueryOptions<Core.Models.Entities.Business> query)
{
    var businessREST = _businessRepo.Get(businessId, query);

    response = Request.CreateResponse(HttpStatusCode.OK, businessREST);
    response.Headers.Location = new Uri(businessREST.Href);

    return response;
}

It has been suggested that I combine the methods as follows.

Code Sample 2:

[HttpGet]
public HttpResponseMessage Get(string businessId, double latitude, double longitude, string hasOwnProperty, ODataQueryOptions<Core.Models.Entities.Business> query)
{

    if (!String.IsNullOrEmpty(businessId))
    {
        //GET ~/businesses/{businessId}
        var businessREST = _businessRepo.Get(businessId, query);

        response = Request.CreateResponse(HttpStatusCode.OK, businessREST);
        response.Headers.Location = new Uri(businessREST.Href);
    }
    else
    {
        //GET ~/businesses?hasOwnProperty={propertyName}
        //GET ~/businesses?latitude={lat}&longitude={long}&hasOwnProperty={propertyName}
        var businessesREST = (latitude == double.MinValue || longitude == double.MinValue)
            ? _businessRepo.Gets(hasOwnProperty, query)
            : _businessRepo.GetsByLatLong(latitude, longitude, hasOwnProperty, query);

        response = Request.CreateResponse(HttpStatusCode.OK, businessesREST);
        response.Headers.Location = new Uri(businessesREST.Href);
    }

    return response;

}

I'm curious as to see what the current widely accepted best practices are regarding Action Definitions and the reasoning behind them.

Having separate methods is much better for a few reasons:

  1. It is much easier to unit test the individual actions separately.
  2. Having separate actions makes it much less likely that changing the implementation of one action accidentally changes the implementation of other actions.
  3. Combining the methods would mean that a bunch of parameters would be null and you'd have an implicit contract about which parameters should be set together and which parameters should be null in different cases. That's why you're having to add the comments. Separate actions are self-documenting because they make the contract much clearer about how to call your API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM