-1

I'm trying to make simple UI with basic CRUD operations. GET methods work properly but I can't make POST method to work (but, when I want to test POST method via fiddler, it works, data is inserted properly in database...)

My app is divided into layers. API controllers are in one layer, and angularJS code and views are in second layer (web layer). Web layer runs on port 50004, and API layer runs on 54927 port. So i wrote this piece of code in angular file:

var serviceBase = 'http://localhost:54927/';
onlineTesting.constant('ngAuthSettings', {
    apiServiceBaseUri: serviceBase,
    clientId: 'onlineTesting'
});

I found on web that I have to enable cors and add some code in my webconfig file which you can see further below.

This is what i have in my angular file:

var _addCategory = function (category) {
    $http.post(serviceBase + 'api/Categories', category).then(function (response) {
        return response;
    });
};

api controller:

[RoutePrefix("api/Item")]
public class CategoriesController : ApiController
{
    ICategoriesRepository _categoriesRepo;
    ICategoriesServices _categoriesServices;

    public CategoriesController()
    {
        _categoriesRepo = new CategoriesRepository();
        _categoriesServices = new CategoriesServices();
    }

    public HttpResponseMessage Post(Categories category)
    {
        var result = _categoriesServices.AddCategory(category.CategoryType);

        if (result == category.CategoryId)
        {
            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, category);
            return response;
        }
        else
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);

    }
    public IHttpActionResult Get()
    {
        var categories = _categoriesServices.GetCategories();

        return Ok(categories);
    }
    public IHttpActionResult Get(int id)
    {
        var categories = _categoriesServices.GetCategoryById(id);

        return Ok(categories);
    }
    public IHttpActionResult Delete(int categoryId)
    {
        var result = _categoriesServices.RemoveCategoryById(categoryId);

        if (result)
            return Ok();
        else
            return BadRequest("Item ID doesn't exist in database");
    }
    public IHttpActionResult Put(Categories category)
    {
        var result = _categoriesServices.UpdateCategory(category); 

        if (result)
            return Ok();
        else
            return BadRequest("Category has not been updated, please check            your category.");
    }
}

I also, added this in my webconfig file:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>

and this is part of html file where i call addCategory method:

div id="registration-form">
<h3 class="crudheader">Add new category</h3>
<div class='fieldset'>
    <form action="#" method="post" data-validate="parsley">
        <div class='row'>
            <input type="text" maxlength="1000" data-required="true" placeholder="Enter new category"
                   data-error-message="Category is required" data-ng-model="category.categoryType">
            <h5 data-ng-model="message">Place your text here ({{ message }})</h5>
        </div>
        <button type="button" data-ng-click="addCategory(category)">Submitt</button>
    </form>
</div>

When i hit submit button i always get these messages in console tab in Inspect element: Remote Address:127.0.0.1:8888

General

Request URL: myURL (with port 54927)

Request Method:OPTIONS

Status Code:405 Method Not Allowed

Response Headers

HTTP/1.1 405 Method Not Allowed

Cache-Control: no-cache

Pragma: no-cache

Allow: POST,GET,PUT

Content-Type: application/json; charset=utf-8

Expires: -1

Server: Microsoft-IIS/8.0

X-AspNet-Version: 4.0.30319

X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcQVBJIExhYlxEZXNrdG9wXE9ubGluZVRlc3RpbmdcTmV3T25saW5lVGVzdGluZ1xBcGlMYWIuT25saW5lVGVzdGluZy5BcGlMYXllclxhcGlcQ2F0ZWdvcmllcw==?=

X-Powered-By: ASP.NET

Access-Control-Allow-Origin: *

Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept

Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS

Date: Thu, 19 Mar 2015 15:08:24 GMT

Content-Length: 76

Request Headers

OPTIONS http://localhost:54927/api/Categories HTTP/1.1

Host: localhost:54927

Proxy-Connection: keep-alive

Access-Control-Request-Method: POST

Origin: myURL (with url 50004)

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36

Access-Control-Request-Headers: accept, content-type

Accept: /

Referer: myUrl (with port 50004)

Accept-Encoding: gzip, deflate, sdch

Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

3 Answers3

0

I believe you need to do JSON.stringfy() for category that will stringify the object and passed to controller action & remove action & method attribute from form.

Code

var _addCategory = function (category) {
    $http.post(serviceBase + 'api/Categories', JSON.stringfy(category)).then(function (response) {
        return response;
    });
};

on HTML use ng-submit method on form element level

HTML

<form data-validate="parsley" data-ng-submit="addCategory(category)">
    <div class='row'>
        <input type="text" maxlength="1000" data-required="true" placeholder="Enter new category"
               data-error-message="Category is required" data-ng-model="category.categoryType">
        <h5 data-ng-model="message">Place your text here ({{ message }})</h5>
    </div>
    <button type="submit">Submit</button>
</form>

Update

You could also add [FromBody] inside you action parameter

CODE

public HttpResponseMessage Post([FromBody] Categories category) {
    var result = _categoriesServices.AddCategory(category.CategoryType);

    if (result == category.CategoryId) {
        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, category);
        return response;
    } else
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);

}

Hope this could help you, Thanks.

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
0

I found out the solution. I installed CORS package through PM. Then in WebApiConfig file in API layer I added config.EnableCors(), and removed customHeaders from web.config file.

Reason is that i shouldn't have both those lines in web.config and the "config.EnableCors()" at the same time, because config.EnableCors() also allows headers and methods, and if both are in the code, they get in some kind of conflict and my POST won't work then.

0

Adding to what previously mentioned to install CORS package, make sure that you include the below line, [EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "", methods: "")] in the API controller.

Example:

[EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
public class TestController : ApiController
{
    // Controller methods not shown...
}

Reference:

http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Holyangel
  • 31
  • 2