0

I am using Angularjs and ASP.NET Web Api, my $http.get, $http.put and $http.delete work just fine, but when I call $http.post I get 500 Internal Server Error, here is my code:

My Angularjs Controller insert function:

$scope.insert = function () {
    var data = '{ "Id": "1", "Name": "test", "Category": "r", "Price": "456.00" }';

    $http.post('api/products', data).success(function (data) {
        alert("it works");

    }).error(function () {
        console.log(Error);
        alert('Error reading JSON file. - ' + data);
    });   
 }

My model in C#:

public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }

My controller in C#:

    public class ProductsController : ApiController
    {
       public void PostProduct(Product product)
        {
            if (product == null)
            {
                throw new ArgumentNullException("product is NULL");
            }

            try
            {
                con.Open();
                SqlCommand cmd = new SqlCommand();
                cmd = new SqlCommand("INSERT INTO [AdventureWorks2012].[Production].[Product2] ( [Name], [ListPrice], [ProductLine]) VALUES ('" + product.Name + "', '" + product.Price + "', '" + product.Category + "')", con);

                cmd.CommandType = CommandType.Text;
                cmd.ExecuteNonQuery();
                con.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }

Code never reaches brake points in C# controller and throws 500 Internal Server Error.

Please advise.

superconsultant
  • 231
  • 2
  • 6
  • 20

3 Answers3

0

If what you're saying is true and the code execution never reaches your PostProduct() action method in your ProductsController, then the problem must be either earlier in the Web API pipeline (e.g. any global message handlers, filters, etc.) or with the client.

It's easy to eliminate the client code from the process by firing the same request and data to your Web API using Fiddler, Postman, etc. I know it's a basic thing to suggest, but since you didn't clarify if you tried this step or not in your question, I had to mention it.

If the request works correctly when sent like that, then it's a problem with your client code. Otherwise, you need to take a look at the code that's executed on your server before your request gets routed to your controller.

djikay
  • 10,450
  • 8
  • 41
  • 52
  • Here is my put function and as you can see it's the same except I use $http.put instead of $http.post, that's whaat puzzles me: $scope.update = function () { var data = '{ Id: "1", Name: "test", Category: "r", Price: "456.00" }'; $http.put('api/products/', data).success(function (data) { alert("it works"); }).error(function () { alert('Error reading JSON file. - ' + $scope.products[0].Price); }); } – superconsultant Jul 23 '14 at 20:29
0

This is most probably a routing issue. First step is to find out if your routes are setup correctly. Use this tool to debug your routes: http://www.nuget.org/packages/routedebugger

e.g. you might need to use the following url api/products/PostProduct depending on your routing. Also I would put a [HttpPost] attribute above that action method.

If the routing is correct then there might be some issues with your model and how the Json is passed to your action hence the router cant match the correct action method. I recommend you to use Fiddler to inspect the Http request and response and see what is the exact request body.

Aidin
  • 2,134
  • 22
  • 26
  • What I have noticed, when I issue "put" function , Content-Type is text/plain and it works fine, but when i call "post", Content-Type is application/json even if I try to change it like this: $http.defaults.headers.post["Content-Type"] = "text/plain; charset=utf-8"; Why content type is different for these two methods and how to change it if I have to? – superconsultant Jul 23 '14 at 21:29
  • Well i am not sure if changing the content type to text/plain is the way to go however you can do that http://stackoverflow.com/questions/17610238/how-to-change-postcontent-type-in-angularjs – Aidin Jul 23 '14 at 21:38
  • I tried the code from referenced link but content-type still comes out as "application/json". It is very strange, as I mentioned before code for "put" and "post" absolutely identical except one triggers"$http.put" method and the other one "$http.post". So "put" works just fine and "post" not at all. – superconsultant Jul 24 '14 at 04:41
  • It is even more strange, when I set content type to "text/plain" and then preview value of it with javascript alert() it does show that content type has been changed to "text/plain", but when I call $http.post in Google Chrome developer tools, under Network tab, it shows that Content type for POST is "application/json". Any idea? – superconsultant Jul 24 '14 at 05:44
0

UPDATE: Problem solved! I have added Postman extension to my Chrome browser as djikay has suggested and discovered that it sees to POST methods in ProductsController and confused which one to call.

Apparently controllers should only have GET, POST, PUT and DELETE methods, but I have also included another method that I called by GetProduct and GetAllProducts to avoid redundancy. But it looks any other methods added to the controller that is not GET, POST, PUT or DELETE are being considered as POST.

I guess I was working with WebForms to long and need to refresh my MVC knowledge.

In any case both answers have been very helpful to me in finding the solution and I thank you both djikay and Aidin.

superconsultant
  • 231
  • 2
  • 6
  • 20
  • Yes, if you don't specify an `[Http...]` attribute to your method and your method name doesn't follow the Web API naming convention, then it's considered as `POST`([I had a similar question](http://stackoverflow.com/questions/23686841/is-there-a-default-verb-applied-to-a-web-api-apicontroller-method)). – djikay Jul 24 '14 at 16:35