0

I've looked on a number of posts already, but I can't see what I've been doing wrong. I suspect that there is a small issue that I've become blind to. I'm hoping someone can point me in the right direction.

I have an API controller which takes HTTPPost, I have a view which is using an AngularJS controller.

The problem I am having is that I can see the request being posted using Fiddler. However the API controller which takes a parameter of Invoice seems to be receiving null. I've checked other posts on here, and although I've found similar issues I haven't been able to find what is wrong in the implementation I have.

Any Ideas? Code below...

The Models are as below;

    [Serializable]
public class Invoice
{
    [JsonProperty(PropertyName = "invoiceId")]
    public Guid InvoiceId { get; set; }

    [JsonProperty(PropertyName = "customer")]
    public Customer Customer { get; set; }

    [JsonProperty(PropertyName = "productDetails")]
    public Product ProductDetails { get; set; }
}

[Serializable]
public class Product
{
    [JsonProperty(PropertyName = "product")]
    public string ProductName { get; set; }
}

[Serializable]
public class Customer
{
    [JsonProperty(PropertyName = "customerID")]
    public Guid CustomerId { get; set; }
    [JsonProperty(PropertyName = "firstName")]
    public string Firstname { get; set; }
    [JsonProperty(PropertyName = "lastName")]
    public string Lastname { get; set; }
    [JsonProperty(PropertyName = "address1")]
    public string Address1 { get; set; }
    [JsonProperty(PropertyName = "address2")]
    public string Address2 { get; set; }
    [JsonProperty(PropertyName = "town")]
    public string Town { get; set; }
    [JsonProperty(PropertyName = "county")]
    public string County { get; set; }
    [JsonProperty(PropertyName = "postCode")]
    public string PostCode { get; set; }
}

The AngularJS controller is as below;

// define angular module/app
var formApp = angular.module('invoice', [])
.controller('invoiceCtrl', function ($scope, $http) {

$scope.invoiceDetails = {
    invoiceId: "fbd7fe22-81b1-4886-8d0e-13be442b8444",
    customer: {
        firstName: "Joe",
        lastName: "Bloggs",
        address1: "1 Somewhere",
        address2: "",
        town: "Oxford",
        county: "OXON",
        postCode: "OX26 5TY"
    },
    productDetails: {
        product:"prod name"
    }
}



// process the form
$scope.processForm = function () {

    $http.post(
        '/api/invoice', 
        JSON.stringify($scope.invoiceDetails),
        {
            headers: {
                'Content-Type': 'application/json; charset=utf-8'
            }
        }


    )
    .success(function (data) {
        console.log(data);

        if (!data.success) {
            // if not successful, bind errors to error variables
            $scope.errorFirstName = data.errors.firstname;
            $scope.errorLastName = data.errors.lastName;
        } else {
            // if successful, bind success message to message
            $scope.message = data.message;
        }
    });
};

});

And the view which posts the details is as below;

<div ng-app="invoice" ng-controller="invoiceCtrl">

    <h2 class="content-margin">Create Invoices using this page</h2>

    <h5 class="content-margin">Invoice ID </h5><span ng-model="invoiceDetails.invoiceId"></span>

    <form class="form-horizontal" ng-submit="processForm()">
        <h4>Customer Details</h4>
        <div class="form-group">
            <label for="Forename" class="control-label col-xs-2">Customer Forename:</label>
            <div class="col-xs-10 col-md-6 col-lg-5">
                <input type="text" class="form-control" id="Forename" placeholder="" ng-model="invoiceDetails.customer.firstName">
            </div>
        </div>
        <div class="form-group">
            <label for="Surname" class="control-label col-xs-2">Customer Surname:</label>
            <div class="col-xs-10 col-md-6 col-lg-5">
                <input type="text" class="form-control" id="Surname" placeholder="" ng-model="invoiceDetails.customer.lastName">
            </div>
        </div>
        <div class="form-group">
            <label for="AddressLine1" class="control-label col-xs-2">Address Line 1:</label>
            <div class="col-xs-10 col-md-6 col-lg-5">
                <input type="text" class="form-control" id="AddressLine1" placeholder="" ng-model="invoiceDetails.customer.address1">
            </div>
        </div>
        <div class="form-group">
            <label for="AddressLine2" class="control-label col-xs-2">Address Line 2:</label>
            <div class="col-xs-10 col-md-6 col-lg-5">
                <input type="text" class="form-control" id="AddressLine2" placeholder="" ng-model="invoiceDetails.customer.address2">
            </div>
        </div>
        <div class="form-group">
            <label for="City" class="control-label col-xs-2">City:</label>
            <div class="col-xs-10 col-md-6 col-lg-5">
                <input type="text" class="form-control" id="City" placeholder="" ng-model="invoiceDetails.customer.town">
            </div>
        </div>
        <div class="form-group">
            <label for="County" class="control-label col-xs-2">County:</label>
            <div class="col-xs-10 col-md-6 col-lg-5">
                <input type="text" class="form-control" id="County" placeholder="" ng-model="invoiceDetails.customer.county">
            </div>
        </div>
        <div class="form-group">
            <label for="PostCode" class="control-label col-xs-2">Post Code:</label>
            <div class="col-xs-10 col-md-6 col-lg-5">
                <input type="text" class="form-control" id="PostCode" placeholder="" ng-model="invoiceDetails.customer.postCode">
            </div>
        </div>

        <input type="submit" name="Submit" value="Submit" class="btn btn-success btn-large" />

</form>

</div>

EDIT

The controller action being called is as below;

[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody]Invoice invoiceDetails)
{
    if (invoiceDetails == null) return this.Request.CreateResponse(HttpStatusCode.BadRequest);

  //  _invoiceRepository.Add(value);

    return this.Request.CreateResponse(HttpStatusCode.OK, new { });
}

The post is as per below

    {
    "invoiceId": "fbd7fe22-81b1-4886-8d0e-13be442b8444",
    "customer": {
        "firstName": "Joe",
        "lastName": "Bloggs",
        "address1": "1 Somewhere",
        "address2": "",
        "town": "Oxford",
        "county": "OXON",
        "postCode": "OX26 5TY"
    },
    "product": {
        "productName": "Prod reg"
    }
  }
10
  • 3
    You shouldn't need to stringify your data. $http.post('/api/invoice', $scope.invoiceDetails) should suffice. Angular defaults to application/json for POST requests too. It may also be worth posting your ApiController definition as you may not have named the action correctly or decorated your parameters Commented Apr 30, 2015 at 11:58
  • I've added the controller to the question and made the changes you've recommended. It's easier to read, so that's helpful but I'm still getting the same problem Commented Apr 30, 2015 at 12:05
  • Try public async Task<HttpResponseMessage> Post([FromBody]Invoice value)? Commented Apr 30, 2015 at 12:08
  • Just tried that it 'value' was still null Commented Apr 30, 2015 at 12:11
  • Try renaming the param, Post(Invoice value) to Post(Invoice invoiceDetails) Commented Apr 30, 2015 at 12:14

1 Answer 1

1

The main problem is Serializable attribute on your models. If you remove them everything will work fine. If you need this attribute for some other stuff and can't remove, then you can add JsonObject attribute:

[JsonObject]
[Serializable]
public class Invoice
{
    // Properties
}

Don't forget to do it for all classes that are deserialized from JSON.

Also in last JSON sample that you posted you have carDetails instead of productDetails. I think it's just a typo.

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

3 Comments

I made the change in adding the JsonObject but that returned a HTTP500, I then tried wiht just JsonObject, that seemed to do the same thing. I removed all attributes on the model, but that didn't seem to make any difference
Can you provide error details? Because it works well in my test project. Usually 500 indicates some problem in your code. Can you debug it?
Ah it worked, seems there was was an issues with an incorrect version of NewtonSoft.Json referenced. the solution worked.

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.