0

I have your typical API Route, however I need it to still return with the Ok JSON blob that it is using, however I need to specify the HttpStatusCode as something different.

Here is the API method.

    [Route("detailedvarinfo/{VarGUID}")]
    public async Task<IHttpActionResult> GetDetailedVarInfo(string VarGUID)
    {

        if (!User.IsInRole("Admin"))
        {
            var DashboardAccess = (from DR in AuthDb.DashboardAccessVars
                                   where DR.ApplicationUser.Id == userInfo.Id
                                   select DR).
                                   AsEnumerable()
                                   .Select(x => new
                                   {
                                       VarGUID = x.VarGUID
                                   }).ToList();

            var FilteredVarInfo = VarInfo.Join(DashboardAccess, x => x.VarGUID, y => y.VarGUID, (x, y) => x);
            if (FilteredVarInfo.Any())
            {
                return Ok(FilteredVarInfo.FirstOrDefault());
            }
            else
            {
                return Ok(HttpStatusCode.Forbidden);
            }

        }
   }

I looked at implementing this but did not have any luck. Return content with IHttpActionResult for non-OK response

Also tried to do something like this.. but did not have any luck.

     public class NotAllowedOkResult<T> : OkNegotiatedContentResult<T>
{
    public NotAllowedOkResult(T content, ApiController controller, HttpStatusCode statusCode)
        : base(content, controller)
    {

    }

    public NotAllowedOkResult(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request,
        IEnumerable<MediaTypeFormatter> formatters, HttpStatusCode statusCode)
        : base(content, contentNegotiator, request, formatters)
    {

    }



    public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await     base.ExecuteAsync(cancellationToken);

        return response;
    }        
}
Community
  • 1
  • 1
MTAG11
  • 396
  • 2
  • 8
  • 23
  • It's not an "OK" result if you want to return a different status. Each status has a "reason phrase" associated with it. The "reason phrase" for status 200 is "OK". So, even if you do have to write custom code to do this, please *don't* describe it as an "OK" result unless, specifically, you're returning status 200. – Damien_The_Unbeliever Aug 07 '15 at 14:37
  • Yeah.. I'm just now realizing this. The reason I'm running into this is that I built this beautiful dashboard that works great with the API.. however I got a new requirement to lock down some of the information. So I want to return a status of 200, because its technically an OK result, but I want to describe that the response had no data because they were filtered.. – MTAG11 Aug 07 '15 at 14:42
  • Basically I'm looking for status 200 - but specify that the statustext is 'filtered' – MTAG11 Aug 07 '15 at 14:45

2 Answers2

1

Got it working! Was really pretty close, needed to do just a bit more work.

API Method

[Route("detailedvarinfo/{VarGUID}")]
public async Task<IHttpActionResult> GetDetailedVarInfo(string VarGUID)
{

    if (!User.IsInRole("Admin"))
    {
        var DashboardAccess = (from DR in AuthDb.DashboardAccessVars
                               where DR.ApplicationUser.Id == userInfo.Id
                               select DR).
                               AsEnumerable()
                               .Select(x => new
                               {
                                   VarGUID = x.VarGUID
                               }).ToList();

        var FilteredVarInfo = VarInfo.Join(DashboardAccess, x => x.VarGUID, y => y.VarGUID, (x, y) => x);
        if (FilteredVarInfo.Any())
        {
            return Ok(FilteredVarInfo.FirstOrDefault());
        }
        else
        {
            return NotAllowedOk(FilteredVarInfo, StatusReason.StatusFiltered);
        }

    }
}

BaseApiController : ApiController

protected internal virtual NotAllowedOkResult<T> NotAllowedOk<T>(T content, StatusReason statusReason)
{
    return new NotAllowedOkResult<T>(content, this, statusReason);
}  

StatusReason Enumeration

public enum StatusReason
{
    StatusFiltered
}

NotAllowedOkResult Class

public class NotAllowedOkResult<T> : OkNegotiatedContentResult<T>
{
    public NotAllowedOkResult(T content, ApiController controller, StatusReason statusReason)
        : base(content, controller)
    {
        statusReasonCode = statusReason;
    }

    public NotAllowedOkResult(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request,
        IEnumerable<MediaTypeFormatter> formatters, StatusReason statusReason)
        : base(content, contentNegotiator, request, formatters)
    {
        statusReasonCode = statusReason;
    }

    protected StatusReason statusReasonCode { get; set; }


    public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await base.ExecuteAsync(cancellationToken);
        response.ReasonPhrase = GetStatusText(statusReasonCode);

        return response;
    }

    private static String GetStatusText(StatusReason reasonCode)
    {
        var retVal = "Unknown";
        switch (reasonCode)
        {
            case StatusReason.StatusFiltered:
                retVal = "Filtered";
                break;
        }
        return retVal;
    }
}

Javascript Result

varService.getDetailedJobInfo($stateParams.varGUID).then(function(results) {
    $scope.varDetails = results.data;
    return results;
}, function (error) {
    //alert(error.data.message);
});
//
// Actual result comes back properly!
//
results = {
   content: datablob,
   status: 200,
   statusText: "Filtered",
   config: datablob
}
MTAG11
  • 396
  • 2
  • 8
  • 23
0

You can use HttpResponseMessage to customize the response.

HttpResponseMessage msg=new HttpResponseMessage(HttpStatusCode.OK);
msg.ReasonPhrase="Filterd";

return msg;