1

I hope you guys can help me.

I have a simple project still in its infancy, but cannot get the AngularJS Controller (ingredientAdmin.controller) to find my C# API controller.

I get an Error: 404 / Not Found: Request URL: http://localhost:31021/api/ingredientAdmin/PostIngredient/

My AngularJS controller and C# controller is in different projects, and I have referenced my C# controller project in my AngularJS project.

I have also tried various spellings etc., but think I might be missing something.

Here is my AngularJS controller: ingredientAdminController:

(function () {
    "use strict";
    var controllerId = 'admin';

    angular
        .module('app.ingredientAdmin')
        .controller('ingredientAdminController', ingredientAdminController, controllerId);

    ingredientAdminController.$inject = ['$http', '$scope', 'common'];

    function ingredientAdminController($http, $scope, common) {
        var vm = $scope;
        vm.formSubmmision = true;
        vm.title = 'Ingredients Admin';
        vm.ingredientData = null;
        vm.save = save;

        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);

        activate();

        function activate() {
            common.activateController([], controllerId)
                .then(function () { log('Activated Admin View'); });
        }

        // Save

        function save() {
            if (vm.formIngredientsAdmin.$valid) {
                postNewData();
            }
            else {
                logger.error('Error: Validation failed. Please correct data and try again');
                vm.formSubmmision = false;
            }
        }

        function postNewData() {
            //prepare data 
            var data = {
                IngredientId: 0,
                IngredientName: vm.NewIngredient.IngredientName,
                IngredientDescription: vm.NewIngredient.IngredientDescription
            }


            $http.post('/api/ingredientAdmin/PostIngredient/', data)
                .then(postDataComplete)
                .catch(getDataFailed);

            function postDataComplete(response) {
                vm.NewIngredient = null;
                vm.formSubmmision = true;
                vm.formIngredientsAdmin.$setPristine();
                vm.formIngredientsAdmin.$setUntouched();
                return vm.NewIngredient;
            }

            function getDataFailed(error) {
                log('Failed to create new Ingredient ' + error.data.Message);
                return;
            }

        }


    };


}
)();

Here is my C# controller: IngredientAdminController:

using System.Net;
using System.Net.Http;
using System.Web.Http;
using RecipeManager.Models;
using RecipeManager.DTO;
using RecipeManger.Common;

namespace RecipeManager.Controllers.Api
{
    public class IngredientAdminController : ApiController
    {
        private RecipeManager.DTO.IngredientAdminDTO dto = new IngredientAdminDTO();

        [HttpPost]
        public HttpResponseMessage PostIngredient(Ingredient ingredient)
        {
            try
            {
                CommandResult<Ingredient> result = dto.CreateIngredient(ingredient);
                return Request.CreateResponse(HttpStatusCode.OK, result);

            }
            catch (RecipeManagerException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

        //[Authorize(Roles = "Admin, SupportCallIndex")]
        public HttpResponseMessage UpdateIngredient(Ingredient ingredient)
        {
            try
            {
                CommandResult<Ingredient> result = dto.UpdateIngredient(ingredient);
                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (RecipeManagerException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

        [HttpPost]
        //[Authorize(Roles = "Admin, SupportCallIndex")]
        public HttpResponseMessage DeleteIngredient(Ingredient ingredient)
        {
            try
            {
                CommandResult<Ingredient> result = dto.DeleteIngredient(ingredient);
                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (RecipeManagerException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

        public HttpResponseMessage GetAll()
        {
            try
            {
                CommandResult<Ingredient> result = dto.ReadIngredient();
                return Request.CreateResponse((result.Status == CommandStatus.Success ? HttpStatusCode.OK : HttpStatusCode.InternalServerError), result);
            }
            catch (RecipeManagerException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }


    }
}

Here is my WebApiConfig code:

using System.Web.Http;
using Microsoft.Owin.Security.OAuth;

namespace RecipeManager.UI.Htmll5
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {

            config.MapHttpAttributeRoutes();

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

This is the structure of my app skeleton:

App Layout

Thank you greatly!

2
  • 3
    You need to POST to /api/ingredientAdmin, not to /api/ingredientAdmin/PostIngredient/ Commented Apr 11, 2016 at 14:54
  • 3
    Or add a new route: api/{controller}/{action}/{id} Commented Apr 11, 2016 at 14:59

3 Answers 3

2

If you want to keep your code as it currently is, then add this route before the default:

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

as mentioned by @Lex, added defaults for id param.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the advice. I am sure this is my issue (one of them), but I simply can't get it to work. Still getting the same error. I did change the routeTemplate to include the {action}. Is there anything else I could be missing? When debugging, it jumps straight from my $http.post request to my error catch.
Have you tried debugging the api controller just to check it hits?
@onmyway You'll probably have to mark {id} as optional using the defaults property.
1

WebApi / HttpPost has a few weird caveats about it.

See my answer (not question, but my answer) here:

Web api not supporting POST method

Note the Method on the Api Controller:

  [System.Web.Http.HttpPost]
    public MyOutputObject DoSomething([FromBody]MyInputObject args)
    {
        Console.Writeline(args.ToString());
    }

Please note this article:

http://www.dontpaniclabs.com/blog/post/2013/01/23/That-Pesky-Requested-Resource-Does-Not-Support-HTTP-Method-POST-Error-When-Using-MVC-Web-API/

and this article

http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/

1 Comment

Thanks for your feedback. Unfortunately still stuck on this one.
1

You can add RoutePrefix and Route into your controller:

[RoutePrefix("api")]

    public class IngredientAdminController : ApiController
        {
            private RecipeManager.DTO.IngredientAdminDTO dto = new IngredientAdminDTO();

        [Route("PostIngredient")]
        [HttpPost]

        public HttpResponseMessage PostIngredient(Ingredient ingredient)
        {
            try
            {
                CommandResult<Ingredient> result = dto.CreateIngredient(ingredient);
                return Request.CreateResponse(HttpStatusCode.OK, result);

            }
            catch (RecipeManagerException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

And your request:

var req = {
method: 'POST',
url: '/api/PostIngredient',
data: data
};

$http(req).then(function successCallback(responseSuccess) {

                        }, function errorCallback(responseError) {

                        });

hope it help.

2 Comments

Thanks for the help. I like your method. Unfortunately I still get the 404: localhost:31021/api/ingredientAdmin/PostIngredient not found. I have decided to dig a bit deeper, and am busy with some tutorials on WebApi front to back. I will revert when I have solved the issue.
try localhost:3021/api/PostIngredient address, without "ingridientAdmin", hope it help, if not - let me know.

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.