Search code examples
javascript.netangularjsasp.net-web-apiangular-resource

Angularjs $resource multiple POST


I have multiple Web Api Post methods like:

    [HttpPost]
    public async Task<IHttpActionResult> Post([FromBody] AdModel adModel)
    {
        //Post
    }

    [HttpPost]
    [Route("AddToWatchList")]
    public async Task<IHttpActionResult> AddToWatchList(int adId)
    {
        // Post to database
    }

Here is my AngularJs Server:

app.factory('adService', ['$resource', 'ngAuthSettings', function ($resource, ngAuthSettings) {

      var serviceBase = ngAuthSettings.apiServiceBaseUri;

return $resource(serviceBase + 'api/Ads/', {}, {
            addToWatchList: {
            method: 'POST',
            url: serviceBase + 'api/Ads/addToWatchList'
           }
        }
    });
}]);

AngularJs Controller:

app.controller('listCategoryAdsController',
    ['ngAuthSettings', '$scope', 'adService', '$routeParams', '$location',
    function (ngAuthSettings, $scope, adService, $routeParams, $location) {

    $scope.addToWatchlist = function (adId) {
        adService.addToWatchList({ adId: adId }).$promise.then(
            function(result) {
                var path = $location.path();
                $location.path(path).search('nw', 1);
            },
            function (error) {

        });
    };

My Html from where I am calling method:

<div class="col-sm-3 text-right price-box" data-ng-repeat="ad in Ads">
     <h2 class="item-price">
         $ {{ad.price}}
     </h2>
     <i class="fa fa-certificate">
     </i>
     <a ng-click="addToWatchlist(ad.adId)" class="btn btn-default  btn-sm make-favorite" tooltip="Click to add to watch list"
           tooltip-placement="left"
           tooltip-trigger="mouseenter">
          <i class="fa fa-heart"></i>
           <span>Watch list</span>
     </a>
</div>

My problem is Post([FromBody] AdModel adModel) is being called perfectly. But when I call AddToWatchList(int adId) I am getting :

POST http://localhost:8081/api/Ads/addToWatchList 404 (Not Found)


Solution

  • You are sending a simple type (int) to AddToWatchList(), therefore Web API is looking in the URI for the adId parameter.

    If the parameter is a “simple” type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.) For complex types, Web API tries to read the value from the message body, using a media-type formatter. More on this..

    You have a few options:

    1 - Send adId through the URI... api/ads/addtowatchlist?adId=123

    $resource(serviceBase + 'api/Ads/addToWatchList', { }, {
        addToWatchList: { method:'POST', params:{ adId:adId } }
    });
    

    2 - Obviously use a complex object as you are doing in the first method. Although it feels silly having a class with a single int property... this is why you and I don't like this approach. But if you already have an Ad class, nothing wrong with reusing it.


    3 - Try this solution which requires in which you would add [FromBody] to your int parameter. And send the adId in with no identifier

    =123