2

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.

1 Answer 1

7

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.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.