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"
}
}
stringifyyour data.$http.post('/api/invoice', $scope.invoiceDetails)should suffice. Angular defaults toapplication/jsonfor POST requests too. It may also be worth posting yourApiControllerdefinition as you may not have named the action correctly or decorated your parameterspublic async Task<HttpResponseMessage> Post([FromBody]Invoice value)?Post(Invoice value)toPost(Invoice invoiceDetails)