0

I am trying to create a function in an Angular controller which passes an array of TestExpense objects to a C# API which will then handle inserting them into a database. Currently, the API is only configured to do one at a time.

The objects of the array, $scope.TestExpenses, I wish to pass are represented by the following constructor :

function TestExpense(employeeId, expenseDate, taskId, expenseTypeId, billingCategory, notes, amount, lastUpdatedDate, lastUpdatedBy, dateSubmitted) { this.employeeId = employeeId; this.expenseDate = expenseDate; this.taskId = taskId; this.expenseTypeId = expenseTypeId; this.billingCategory = billingCategory; this.notes = notes; this.amount = amount; this.lastUpdatedDate = lastUpdatedDate; this.lastUpdatedBy = lastUpdatedBy; this.dateSubmitted = dateSubmitted; this.location = location; } $scope.TestExpenses = []; 

The current state of the relevant Angular function submitEntriesToDatabase:

$scope.submitEntriesToDatabase = function () { $http.post('/expense/submitExpense', $scope.TestExpenses) .success(function (data, status, headers, config) { }) .error(function (data, status, headers, config) { }); }; 

In C#, I have the following model to correspond to my TestExpense object:

public class Expense { public int employeeId { get; set; } public string expenseDate { get; set; } public int taskId { get; set; } public int expenseTypeId { get; set; } public int billingCategory { get; set; } public string notes { get; set; } public float amount { get; set; } public string LastUpdatedDate { get; set; } public int LastUpdatedBy { get; set; } public string dateSubmitted { get; set; } public string location { get; set; } } 

And the method to handle the POST in the API:

 public void SubmitExpenses(List<Expense> expenses) { //using(cnxn) //{ // using(SqlCommand sqlQuery = new SqlCommand("INSERT INTO Expenses " + // "(Employee_ID, Task_ID, Expense_Date, Expense_Type_ID, Billing_Category_ID, " + // "Amount, Notes, Last_Updated_By, Last_Update_Datetime, Date_Submitted, Location) " + // "Values (@employeeId, @taskId, @expenseDate, @expenseTypeId, @billingCategory, @amount, @notes, " + // "@lastUpdatedBy, @lastUpdatedDate, @dateSubmitted, @locationId)", cnxn)) // { // sqlQuery.Parameters.Add(new SqlParameter("@employeeId", SqlDbType.Int) { Value = employeeId }); // sqlQuery.Parameters.Add(new SqlParameter("@expenseDate", SqlDbType.DateTime) { Value = expenseDate }); // sqlQuery.Parameters.Add(new SqlParameter("@taskId", SqlDbType.Int) { Value = taskId }); // sqlQuery.Parameters.Add(new SqlParameter("@expenseTypeId", SqlDbType.Int) { Value = expenseTypeId }); // sqlQuery.Parameters.Add(new SqlParameter("@billingCategory", SqlDbType.Int) { Value = billingCategory }); // sqlQuery.Parameters.Add(new SqlParameter("@notes", SqlDbType.Text) { Value = notes }); // sqlQuery.Parameters.Add(new SqlParameter("@amount", SqlDbType.Money) { Value = amount }); // sqlQuery.Parameters.Add(new SqlParameter("@lastUpdatedDate", SqlDbType.DateTime) { Value = lastUpdatedDate }); // sqlQuery.Parameters.Add(new SqlParameter("@lastUpdatedBy", SqlDbType.Int) { Value = lastUpdatedBy }); // sqlQuery.Parameters.Add(new SqlParameter("@dateSubmitted", SqlDbType.DateTime) { Value = dateSubmitted }); // sqlQuery.Parameters.Add(new SqlParameter("@locationId", SqlDbType.VarChar) { Value = "Radnor" }); // cnxn.Open(); // sqlQuery.ExecuteNonQuery(); // } //} } 

The lines that are commented out in my SubmitExpenses work to insert a single entry (with the appropriate method signature, not what is there now). It is also that functionality which I wish to imitate with the List<Expenses> expenses argument being passed to it. From what I gather, I need to deserialize the JSON string that will represent my $scope.TestExpenses array, but I am unsure of how to start to parse out individual Expense objects from it.

The relevant route in RouteConfig.cs:

routes.MapRoute( name:"SubmitExpense", url:"expense/submitExpense", defaults: new { controller = "Expense", action = "SubmitExpenses" } ); 

Any guidance would be much appreciated!

5
  • What is the route that has been setup, how has that been applied to this function?CommentedAug 12, 2016 at 15:34
  • It is as seen in the $http.post. I know that data is passed to the SubmitExpenses method in my controller, but I am unaware of how to break down the List passed as an argument, which I feel is a problem independent of route.CommentedAug 12, 2016 at 15:41
  • I edited the post because I hadn't properly indented the SubmitClasses method header. Sorry.CommentedAug 12, 2016 at 15:43
  • Please clarify how the SubmitExpenses function gets called on your server.
    – plong0
    CommentedAug 12, 2016 at 15:57
  • The route is posted, but I do not really see how it is relevant since I know the application and API are connected. Literally, only the method header is changed, which has nothing to do with the routes.CommentedAug 12, 2016 at 16:02

3 Answers 3

2

From what I gather, I need to deserialize the JSON string that will represent my $scope.TestExpenses array, but I am unsure of how to start to parse out individual Expense objects from it.

Simple. Use the [FromBody] decorator in your method signature. Your default JSON serializer settings setup for all the controllers will try parse the string into the Expense list - if you're using Json.NET, it can handle this automatically.

public void SubmitExpenses([FromBody] List<Expense> expenses) 
3
  • I will try this now. So I should be able to access an element from the expenses argument as an Expense object by its index, and then access each individual element's properties?CommentedAug 12, 2016 at 16:11
  • +1 for your help, @toadflakz. I didn't actually require [FromBody] as detailed by @naveen, but I appreciate you did help me get on the right path.CommentedAug 12, 2016 at 16:36
  • he is correct. its just that web api uses JSON.NET +1CommentedAug 12, 2016 at 16:44
1

From what I gather, I need to deserialize the JSON string that will represent my $scope.TestExpenses array, but I am unsure of how to start to parse out individual Expense objects from it.

No. You don't need to do a thing to de-serialize. It will be auto-deserialized.

A better implementation of the POST request will be this.

$scope.submitEntriesToDatabase = function() { var config = { method: "POST", url: '/expense/submitExpense', data: $scope.TestExpenses }; $http(config).then(function(response) { //success }, function(response) { //error }); }; 

If the property names in the array are same as that of the the object in your generic list, the web api will automatically convert the javascript array to List<T>.

P.S: Do not use .success and .error callbacks as they are obsolete. Use .then

2
  • Thank you very much! Also, +1 for giving me insight into proper usage for $http.postCommentedAug 12, 2016 at 16:34
  • $http.post is equally good. $http gives us more control. its also more readable in my opinionCommentedAug 12, 2016 at 16:43
0

The correct way to do a post in angular 1.x, using $http is:

$http.post('/my/url',{foo:bar}).then(function(result) { console.log(result.data); // data property on result contains your data }); 

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.