4

I want to create extension method for ApiController to be able to return custom content.
My idea is to return custom error with my own details. I want to return custom error similar to errors returned by OAuthAuthorizationServerProvider:

{
  "error": "invalid_grant",
  "error_description": "You have 3 more attempts before Your account will be locked."
}

Inside my ApiController I've added this method:

public IHttpActionResult Test()
{
    HttpError err = new HttpError();
    err["error"] = "40001";
    err["error_description"] = "Something is wrong";
    var response = Request.CreateErrorResponse(HttpStatusCode.NotFound, err);
    return ResponseMessage(response);
}

This gives me nice looking response:

{
    "error": "40001",
    "error_description": "Somethis is wrong"
}

I've tried converting this to below extension method:

public static class ApiControllerExtensions
{
    public static IHttpActionResult BadRequest(this ApiController apiController, string error, string errorDetails)
    {
        HttpError err = new HttpError();
        err["error"] = error;
        err["error_description"] = errorDetails;
        var response = apiController.Request.CreateErrorResponse(HttpStatusCode.NotFound, err);
        return apiController.ResponseMessage(response);
    }
}

but I get error: Cannot access protected internal method 'ResponseMessage' here

I know I can create custom base ApiController and add that method there, but I'd like to create extension method so it will be easier to reuse it in other projects.

How can I return IHttpActionResult from ApiController extension method?

Misiu
  • 4,738
  • 21
  • 94
  • 198
  • Can you derive your own CustomApiController class from ApiController and implement a public virtual ResponseMessage method which calls the internal base one? Then you would write your extension method for CustomApiController – benjrb Jan 05 '17 at 09:31
  • keep it in your base class. It's the same. – Amit Kumar Ghosh Jan 05 '17 at 09:33
  • @benjrb I'm aware I can do this that way, but whats the point of having extension method if I still would need to use CustomApiController. I want to avoid that and have extension class for ApiController, not for custom base class – Misiu Jan 05 '17 at 09:34

1 Answers1

1

I've managed to fix my extension method.
Instead of return apiController.ResponseMessage(response) I've added return new ResponseMessageResult(response)

Below is working extension method:

public static class ApiControllerExtensions
{
    public static IHttpActionResult InvalidRequest(this ApiController apiController, string error, string errorDetails = "", ModelStateDictionary modelState = null)
    {
        var err = modelState != null ? new HttpError(modelState, false) : new HttpError();
        if (err.ContainsKey("message"))
            err.Remove("message");
        err["error"] = error;
        if (!string.IsNullOrWhiteSpace(errorDetails))
            err["error_description"] = errorDetails;
        var response = apiController.Request.CreateErrorResponse(HttpStatusCode.BadRequest, err);

        return new ResponseMessageResult(response);
    }

    public static IHttpActionResult InvalidRequest(this ApiController apiController, string error, ModelStateDictionary modelState = null)
    {
        return InvalidRequest(apiController, error, null, modelState);
    }
}

and sample usages looks like this:

return this.InvalidRequest("error")

return this.InvalidRequest("error","error details")

var msd = new ModelStateDictionary();
msd.AddModelError("name", "name not valid");

return this.InvalidRequest("error",msd);
return this.InvalidRequest("error","details",msd);

returned JSON (400 Bad Request) looks like this:

{
    "error": "error",
    "modelState": {
        "name": [
            "name not valid"
        ]
    },
"error_description": "details"
}
Misiu
  • 4,738
  • 21
  • 94
  • 198