1

I have this problem with an MVC application that has a class descended from ApiController:

[Authorize]
public class WidgetController : ApiController
{
    // POST: api/Widget/GetWidgets
    [HttpPost]
    [ActionName("GetWidgets")]
    public List<WidgetItem> GetWidgets(WidgetQueryParams parms)
    {
        // ...
    }

    // ...
}

This is configured in WebApiConfig.cs:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Filters.Add(new ExceptionHandlingAttribute());

        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "WidgetApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new {id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new {id = RouteParameter.Optional }
        );
    }
}

The method is called from JavaScript built on top of AngularJS:

function () {
    'use strict';

    angular.module('WidgetApp').factory('DataContext', ['$http', '$q', DataContext]);

    function DataContext($http, $q) {
        var service = {
            // ...
            WebAPIPostWithData: WebAPIPostWithData,
            // ...
        };
        return service;
    
        function WebApiPostWithData(Controller, Action, data) {
            var url = "api/" + Controller + "/" + Action;
            var deferred = $q.defer();

            $http.post(url, data)
                .success(function (httpResult) {
                    deferred.resuilve(httpResult);
                }).error(response) {
                    deferred.reject(response);
                    throw "Exception: DataContext/WebAPIPostWithData - Error while calling the url '" + url + "'. Message: " + response.ExceptionMessage;
                })
            return deferred.promise;
        }
    }
})();

At run time, the JavaScript gets down into DataContext.WebAPIPostWithData() and calls $http.post(). When the call returns, I see the code stop at the breakpoint I put on the .error() function and the response is a 403 error. As an experiment, I modified the code in the WidgetController so the GetWidgets() method was decorated as an [HttpGet] method instead of [HttpPost] and the program stopped at my breakpoint in that method.

I'm at a complete loss at this point. Why does the call return a 403 error when it's called as an HTTP POST operation but works fine when called as an HTTP GET operation? Does anyone have any ideas on what might be wrong?

Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123

2 Answers2

2

It could be a CORS pre-flight check error. GET request don't have these restrictions, however POST requests do. With pre-flight check errors, it usually says that. Can you check if it works in Postman? If it works in Postman, but doesn't in your app, then that's another indication that it's a pre-flight check issue.

You may find the below answer useful as well: Response for preflight 403 forbidden

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Prem
  • 36
  • 1
  • Well, you were right, the problem did have to do with CORS pre-flight checks. The issue was actually in some code in the application that was written to process those checks. I've corrected the logic and now it works correctly. – Tony Vitabile May 04 '22 at 22:18
0

Perhaps you have permission to read from the API but not write to it?

JBatstone
  • 167
  • 7
  • As I said, an HTTP GET operation works fine. But I'll look into that in the morning. – Tony Vitabile May 03 '22 at 22:32
  • We have an `AuthorizatonAttribute` class decorating the call and I've stepped through the code in it. The attribute is returning true so the problem isn't there. – Tony Vitabile May 04 '22 at 13:54