I have this AngularJS Http Call
$http({
method: "POST",
url: Helper.ApiUrl() + '/Api/Case/SendCase',
data: { obecttype1, obj2, obj3},
}).then(function mySuccess(response) {});
Ant this ASP.net Web Api method
[HttpPost]
[Route("Api/Path/SendCase")]
public int SendCase(object application)
{
string applicantName = ((Newtonsoft.Json.Linq.JObject)application)["applicant"].ToString();
obecttype1 obj = JsonConvert.DeserializeObject<obecttype1>(((Newtonsoft.Json.Linq.JObject)application)["obecttype1"].ToString());
.........................
return ID;
}
This works pretty well, but I feel it is a bit dirty because I am parsing my objects in my method, so my question is
Is the are way to send multiple objects as params in a POST method, I would prefer to avoid modifying my model, avoid creating a class for this
So my Api Method would look like this
public int SendCase(class1 obecttype1, class2 obj2, class3 obj3)
"Is the are way to send multiple objects as params in a POST method, I would prefer to avoid modifying my model, avoid creating a class for this"
By design HTTP Post can only have one body and web api will try to cast the body to the parameter defined in the method signature. So sending multiple objects in the body and trying to match these against multiple params in the method signature will not work. For that you need to define a class which holds the other classes and match the body signature.
public class postDTO
{
public class1 class1Data { get; set; }
public class2 class2Data { get; set; }
public class3 class3Data { get; set; }
}
//The api signature
public int SendCase(postDTO application)
If you still don't want to add the new class then I would use the JObject directly as the parameter as this
[HttpPost]
public int SendCase(JObject jsonData)
{
dynamic json = jsonData;
JObject class1DataJson = json.class1Data;
JObject class2DataJson = json.class2Data;
JObject class3DataJson = json.class3Data;
var class1Data = class1DataJson.ToObject<class1>();
var class2Data = class2DataJson.ToObject<class2>();
var class3Data = class3DataJson.ToObject<class3>();
}
1. Define models for the parameters
public class ClassType1
{
public int Num1 { get; set; }
public string Str1 { get; set; }
}
public class ClassType2
{
public double Test2 { get; set; }
}
2. Use the models as the parameters on the API controller method
// Sorry this example is setup on .Net Core 2.0 but I think the previous
// versions of Web Api would have similar/same behavior
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpPost]
public void Post(ClassType1 ct1, ClassType2 ct2)
{}
}
3. When posting, your objects inside the data {} have to have the keys that match the parameter name you defined on the Controller method
jQuery ajax
$.ajax({
method: 'post',
url: 'http://localhost:53101/api/values',
dataType: 'json',
data: {
// It takes key value pairs
ct1: {
num1: 1,
str1: 'some random string'
},
ct2: {
test2: 0.34
}
}
});
To summarize, yes you can post multiple objects back to the server, as long as
You define a key for each object and the key has to match the parameter name you define on the server method.
The object structure has to match.
-- update --
Just as a proof, here is the screenshot:
We have an app that uses DefaultHttpBatchHandler to accept multi-part POST requests. I believe it to be a bit clunky for many reasons but it is the built-in way to accept multiple objects on a single request in a structured fashion.
https://msdn.microsoft.com/en-us/library/system.web.http.batch.defaulthttpbatchhandler(v=vs.118).aspx
As for the script to create something, that I don't know about. Our callers that use this API are C# services that can create the multi-part requests using a simple client library we provide to help them do just that.
Related
I'm trying to call a .NET Core API from AngularJS. In the AngularJS I'm calling the method like this:
$http({
method: 'POST',
url: '/api/message/transaction/' + this.transaction.id,
data: { "transactionJson": "hello"}
})
.then(function (response) {
var r = response;
})
My .NET Core API method is like this:
[Route("~/api/message/transaction/{transactionId}")]
[HttpPost]
public async Task<ActionResult<DeviceEventsTransactionmsg>> PostTransaction([FromBody] string transactionJson)
{
I'm getting a 400 Bad Request response back from the server. How do I fix it?
I realised the type for the parameter must be a type that has a property named TransactionJson, so I need to define a new C# type:
public class TransactionData() {
public string TransactionJson
}
Then in the API method:
[Route("~/api/message/transaction/{transactionId}")]
[HttpPost]
public async Task<ActionResult<DeviceEventsTransactionmsg>> PostTransaction([FromBody] TransactionData transactionJson)
{
getting a 400 Bad Request response back from the server. How do I fix it?
To fix the issue, as your mentioned, one solution is modifying action parameter, like below.
public async Task<ActionResult<DeviceEventsTransactionmsg>> PostTransaction([FromBody] TransactionData transactionJson)
{
//...
//code logic here
TransactionData class
public class TransactionData
{
public string TransactionJson { get; set; }
}
Besides, we can also implement and use a custom plain text input formatter to make PostTransaction action method that accepts a string-type ACTION parameter work well.
public class TextPlainInputFormatter : TextInputFormatter
{
public TextPlainInputFormatter()
{
SupportedMediaTypes.Add("text/plain");
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
{
string data = null;
using (var streamReader = new StreamReader(context.HttpContext.Request.Body))
{
data = await streamReader.ReadToEndAsync();
}
return InputFormatterResult.Success(data);
}
}
Add custom formatter support
services.AddControllers(opt => opt.InputFormatters.Insert(0, new TextPlainInputFormatter()));
Test Result
selectedLocation is always null on the Server
I am using Angular , what is the proper way of passing object to get method
This is Class that is defined on Server, which is being passed as parameter in get request
public class Location
{
public string LocationName { get; set; }
public string MFGName { get; set; }
}
This is the method in WebAPI that is being called.
[HttpGet]
[ActionName("RenewToken")]
[AllowAnonymous]
[ResponseType(typeof(string))]
public async Task<IHttpActionResult> RenewToken(Location selectedlocation)
{
}
The Captured Request looks like this(In google Chrome Developers Tool)
http://localhost:58146/api/Account/RenewToken?selectedlocation=%7B%22LocationName%22:%22Guad%22,%22MFGName%22:%22Flex%22%7D
What am i doing wrong ?
Okay so from what i got from this
Why do we have to specify FromBody and FromUri in ASP.NET Web-API?
when the parameter of the method is a complex type is looks in the body of the request
since you're using GET the data gets put into the uri instead of the body
couple options you could do are
public async Task<IHttpActionResult> RenewToken(string LocationName, string MFGName)
{
}
you could always change your verb to a post or something that accepts data in teh body
You might try changing your get in angular to something like
$http({
method: "GET",
url: "/api/Account/RenewToken",
params: {
LocationName: "Guad",
MFGName: "Flex"
}
})
which will parameterize the data
I have this controller:
public class SeguiAttivazioneController : ApiController
{
[HttpGet]
public IHttpActionResult DoWork1()
{
...
return Ok();
}
[HttpGet]
public IHttpActionResult DoWork2()
{
...
return Ok();
}
[HttpGet] //I would like to have a search with GET verb, but I cannot validate my ModelState with dataAnnotation
public IHttpActionResult AnotherSearch(string filter1, string filter2, ...)
{
if (ModelState.IsValid)
{
...
return Ok();
}
return BadRequest(ModelState);
}
[HttpPost]
public IHttpActionResult DoSearch(SearchFilter filters)
{
if (ModelState.IsValid)
{
...
return Ok();
}
return BadRequest(ModelState);
}
[HttpPost]
public IHttpActionResult SubmitForm(FormData data)
{
...
return Ok();
}
}
As you can see I have two methods with same HttpVerbs (2 for GET and 2 for POST)... I don't know if I am violating REST principles... If so, I would like to avoid...
In this moment I am using AngularJs + NgResources to call my Controller..
public_area
.factory("SeguiAttivazioneService", function ($resource) {
//return {
// seguiAttivazione: $resource("/api/SeguiAttivazione/", null,
// {
// 'get2': { method: 'GET', url: '/api/SeguiAttivazione/GetActivationStatus2' }
// })
//};
return {
seguiAttivazione: $resource("/api/SeguiAttivazione/")
};
});
I am trying to do a GET:
$scope.getActivationStatus = function (event) {
event.preventDefault();
if ($scope.segui_attivazione_form.$valid) {
var request =
new SeguiAttivazioneService
.seguiAttivazione()
.$get({ }, getActivationStatusSuccess, getActivationStatusError);
}
};
But (correctly) I obtain an "Internal Server Error 500", because I have to GET method. How Can I solve this problem? (I suppose I will have same problem with POST too)
Thank you
UPDATE
Here the class of the filters
public class SearchFilter
{
[Required(ErrorMessage="")]
public string CodiceFiscale { get; set; }
[Required(ErrorMessage = "")]
[RegularExpression(#"^(?:\d{11,16})|(?:[a-zA-Z]{6}[a-zA-Z0-9]{2}[a-zA-Z][a-zA-Z0-9]{2}[a-zA-Z][a-zA-Z0-9]{3}[a-zA-Z])$", ErrorMessage = "Codice Fiscale o Partita IVA non validi")]
public string CodiceRichiesta { get; set; }
}
With this class I can use data Annotation to validate my model... If I do a GET Method I cannot use data annotation validation anymore...
Here is some explanation about a the REST Endpoints.
In REST we are manipulating ressources. As collections or individual.
Classics endpoint would be :
GET /rest/houses DATA : none -> will return a collection of houses
GET /rest/houses/{id} DATA : none -> will return the house find by its {id}
POST /rest/houses DATA : {"street":"3 bdv NY-city"} -> will create a new house object with the given data
PUT /rest/houses/{id} DATA : { "id":"{id}", "street":"4 bvd NY-city"} -> will update the whole house ressource find by its {id}
PATCH /rest/houses/{id} DATA : { "street":"4bvd NY-city" } -> will update the given fields of the house ressource find by its {id}
DELETE /rest/houses/{id} DATA : none -> will delete the house ressource find by its id.
There is too much things to know about restfull API that i can't give you all the keys. But try to find some good articles on the subjects such as :
http://www.restapitutorial.com/index.html
Not sure if this answer your question, but i hope it'll help you.
EDIT 1 :
Since i have to add some point about a restfull way to give some complicated action i'll give you the restfull url way to go.
In a restful world (extremely rare) you know only one entry point of your rest API let say this :
GET /rest/
This uri will respond you will all the services that the api can provide
Exemple :
{
"resources":"/rest/ressources",
"apiInfo" : "/rest/api/info"
}
To get your ressources informations you'll follow the link
GET response.resources
I may respond something like :
{
"houses":"/rest/ressources/houses/",
"cars" :"/rest/ressources/cars"
}
Now we want the houses
GET response.houses
Response :
{
"fields":[{
"constructionYear","street"
}],
"search":"/rest/houses"
"create":"/rest/houses"
}
etc... And at this place you can add some non restful endpoints. In a restful way. This action will be hold by a restful resource. Somes API that are using this kind of great Restful.
Standard Rest API :
https://developers.soundcloud.com/docs/api/reference#users
Restful API :
https://www.salesforce.com/us/developer/docs/api_rest/
The question is that the Web API infrastructure must have a way to choose one of the possible methods.
One way is changing the Web API route configuration, including an /{action}/ segment. If you do so it will work exactly like MVC, and you have to always include the action name.
The other way is making the received parameters different in each method, so that the Web API infrastructure can discover which method you're trying to invoke. You can read this answer I've written today for a similar question: How can I add multiple Get actions with different input params when working RESTFUL?.
As a final comment in that answer I say that the parameters can be also discerned by using route contraints.
The first solution of having to include the action name in all invocation is not RESTful, but do you need or prefer it to be RESTful for any particular reason?
Within my project I am trying to perform a save operation that updates my Breeze model as well as passes the updated object to my webAPI. In this project I am not using EF context as the project has been modeled to work with other interfaces. So within my webAPI class I have the following:
[BreezeController]
public class ReportLibraryApiController : ApiController
{
readonly long userid = 1;//testing
readonly IReportLibraryManager manager = new ReportLibraryManager();//interface
//method for share
[Route("reportlibrary/SetReportShare/")]
[HttpPost]
public DTOs.Report SetReportShare(JObject report )
{
//within here I plan to unwrap the JSobject and pull out the necessary
//fields that I need
DTOs.Report updatedreport=null;
//manager.ShareReport(updatedreport.ReportId);
//manager.UnShareReport(updatedreport.ReportId);
return updatedreport;
}
}
The Report Object looks like this
public class Report
{
public Int64 ReportId { get; set; }
public string ReportName { get; set; }
public string ReportDescription { get; set; }
public DateTime? ReportDateCreated { get; set; }
public string ReportOwner { get; set; }
public IEnumerable<ReportLabel> ReportLabels { get; set; }
public bool IsShared { get; set; }
public bool IsFavorite { get; set; }
}
From my angular service I am trying to call the save operation as:
app.factory('reportLibraryService', function(breeze, model){
var serviceName = "reportlibrary/";
var ds = new breeze.DataService({
serviceName: serviceName,
hasServerMetadata: false,
useJsonp: true,
});
var manager = new breeze.EntityManager({ dataService: ds });
model.initialize(manager.metadataStore);
function returnResults(data){ return data.results}
function setReportShare(report) {
var option = new breeze.SaveOptions({ resourceName: 'SetReportShare' })
return manager.saveChanges(null, option).then(returnResults)
};
}
I realize the return results may not be correct but at this point I am just trying to call the save operation in the API. When I run the code everything executes but the save/setting of the share does not fire. A secondary question is I'm still not clear on how the breeze model is updated? Am I supposed to issue a new query from the api and pass that back or is there a way to update the cached object. I'm new to breeze (obviously) and trying to figure out where to look.All the examples I have seen thus far use EF context to perform these actions. However in my case I don't have that option.
Should breeze be making the call or since I am not using EF should I be using $http directive to push the object up. then return a new object to breeze for binding? (that seems a little heavy to me and now how it is designed to work).
I'd appreciate any guidance, or information or how to figure this out.
Edited for more information...
Here is a little more detail based on some of the questions posted by Ward to my original question:
where is your metadata that you code says is not on the server?
The solution I am working on does not expose the EF context this far our. As a result interfaces have been created that handle the queries etc within the project. As a result I don't have the ability to use EF. Very similar to the Edmunds sample. I created a meta definition in the web project which references a report object I have defined. This class is much different from what is returned from the DB but it represents what the UI needs. I created two models
report.cs
public class Report
{
public Int64 ReportId { get; set; }
public string ReportName { get; set; }
public string ReportDescription { get; set; }
public DateTime? ReportDateCreated { get; set; }
public string ReportOwner { get; set; }
public IEnumerable<ReportLabel> ReportLabels { get; set; }
public bool IsShared { get; set; }
public bool IsFavorite { get; set; }
}
model.js
app.factory('model', function () {
var DT = breeze.DataType;
return {
initialize: initialize
}
function initialize(metadataStore) {
metadataStore.addEntityType({
shortName: "Report",
namespace: "Inform.UI.DTOs",
dataProperties: {
reportId: { dataType: DT.Int64, isPartOfKey: true },
reportName: { dataType: DT.String },
reportDescription: { dataType: DT.String },
reportDateCreated: { dataType: DT.String },
reportOwner: { dataType: DT.String },
reportLabels: { dataType: DT.Undefined },
isShared: { dataType: DT.Bool },
isFavorite: { dataType: DT.Bool }
},
navigationProperties: {
labels: {
entityTypeName: "Label:#Inform.UI.DTOs", isScalar: false,
associationName: "Report_Labels"
}
}
});
metadataStore.addEntityType({
shortName: "ReportLabel",
namespace: "Inform.UI.DTOs",
dataProperties: {
labelId: { dataType: DT.Int64, isPartOfKey: true },
reportId: { dataType: DT.Int64 },
labelName: { dataType: DT.String },
isPublic: { dataType: DT.Bool },
reports: { dataType: DT.Undefined }
},
navigationProperties: {
labels: {
entityTypeName: "Report:#Inform.UI.DTOs", isScalar: false,
associationName: "Report_Labels", foreignKeyNames: ["reportId"]
}
}
});
}
})
why are you configuring useJsonp = true ... and then POSTing to the SetReportShare endpoint?
The dataservice was originally defined for GET requests for querying/returning results to the client. I reused the dataservice and tacked on the POST event. Based on your comment though I assume this is a no-no. In looking at the project I am working within the same domain (and always will be) so I don't really think I need jsonp as part of the dataservice definition. Am I wrong in thinking that?
I gather from your question that I should have a separate dataservice for POST's and a separate one for GET's
why is it returning the DTOs.Report type when you can tell by looking at the standard Breeze SaveChanges method that it returns a SaveResult?
This was a typo on my part. The save Result was originally defined as just a JObject. My intent is to return (if necessary) an updated Report object. However I am unsure of the best practice here. If the client (breeze) is updating the cache object. Why do I need to return the report object. Would it not be better to just return a success fail result or boolean of some sort vs. returning an entire report object?
why is your client-side saveChanges callback treating the response as if it came from a query?
This is very simple as you stated, I have no idea what I am doing. I am certainly diving into the deep end as I don't have a choice right now... My question here is when you perform a CRUD operation are these not wrapped in a promise as when performing a query? Or is the promise only important for queries?
Thank you again-
-cheers
You're jumping into the deep end w/o knowing how to swim.
You haven't explained why you're going exotic. That's OK but you want to ease into it. I strongly recommend that you start with the "happy" path - Web API, EF, SQL Server - and then unwind them slowly as you start to understand what's going on.
If you can't do that, at least look at the NoDb sample which doesn't use EF or SQL Server (see the TodoRepository).
You absolutely can do what you're striving to do ... once you know how ... or find someone who does.
At this point, you've created nothing but questions. For example,
where is your metadata that you code says is not on the server?
why are you configuring useJsonp = true ... and then POSTing to the SetReportShare endpoint?
why is it returning the DTOs.Report type when you can tell by looking at the standard Breeze SaveChanges method that it returns a SaveResult?
why is your client-side saveChanges callback treating the response as if it came from a query?
As for your questions:
the breeze model is updated automatically when the save completes
no, you don't issue a new query from the api
yes, you can (and usually do) return the server-updated object back in the SaveResult.
$http (a method not a directive) is used by Breeze itself to communicate to the server; using it directly isn't going to change anything.
Not sure any of my answers help. But I do think you'll be fine if you take it from the top and work deliberately forward from one thing you understand to the next.
I'm looking for a solution to POSTing an array of objects to MVC3 via JSON.
Example code I'm working off of:
http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx
JS:
var data = { ItemList: [ {Str: 'hi', Enabled: true} ], X: 1, Y: 2 };
$.ajax({
url: '/list/save',
data: JSON.stringify(data),
success: success,
error: error,
type: 'POST',
contentType: 'application/json, charset=utf-8',
dataType: 'json'
});
ListViewModel.cs:
public class ListViewModel
{
public List<ItemViewModel> ItemList { get; set; }
public float X { get; set; }
public float Y { get; set; }
}
ItemViewModel.cs:
public class ItemViewModel
{
public string Str; // originally posted with: { get; set; }
public bool Enabled; // originally posted with: { get; set; }
}
ListController.cs:
public ActionResult Save(ListViewModel list)
{
// Do something
}
The result of this POST:
list is set, to a ListViewModel
Its X and Y properties are set
The underlying ItemList property is set
The ItemList contains one item, as it should
The item in that ItemList is uninitialized. Str is null and Enabled is false.
Put another way, this is what I get from MVC3's model binding:
list.X == 1
list.Y == 2
list.ItemList != null
list.ItemList.Count == 1
list.ItemList[0] != null
list.ItemList[0].Str == null
It would appear the MVC3 JsonValueProvider is not working for complex objects. How do I get this to work? Do I need to modify the existing MVC3 JsonValueProvider and fix it? If so, how do I get at it and replace it in an MVC3 project?
Related StackOverflow questions I've already pursued to no avail:
Asp.net Mvc Ajax Json (post Array)
Uses MVC2 and older form-based encoding - that approach fails with an object that contains an array of objects (JQuery fails to encode it properly).
Post an array of complex objects with JSON, JQuery to ASP.NET MVC Controller
Uses a hack I'd like to avoid where the Controller instead receives a plain string which it then manually deserializes itself, rather than leveraging the framework.
MVC3 RC2 JSON Post Binding not working correctly
Didn't have his content-type set - it's set in my code.
How to post an array of complex objects with JSON, jQuery to ASP.NET MVC Controller?
This poor guy had to write a JsonFilter just to parse an array. Another hack I'd prefer to avoid.
So, how do I make this happen?
In addition to { get; set; }, these are some of the conditions for JSON Binding Support:
This is new feature in ASP.NET MVC 3 (See “JavaScript and AJAX Improvements“).
The JSON object’s strings (‘X’, ‘Y’, ‘Str’, and ‘Enabled’) must match ViewModel object’s properties.
ViewModel object’s properties must have { get; set; } method.
Must specify Content Type as “application/json” in the request.
If it's still not working, check the JSON string to make sure it's valid one.
Read more at my post.
Hope that helps!
The problem was that the properties in the models that were in the List did not have get/set on their public properties. Put another way, MVC3's automatic JSON binding only works on object properties that have get and set.
This will not bind:
public string Str;
This will bind:
public string Str { get; set; }
That's strange. I am unable to reproduce your behavior. Here's my setup (ASP.NET MVC 3 RTM):
Model:
public class ItemViewModel
{
public string Str { get; set; }
public bool Enabled { get; set; }
}
public class ListViewModel
{
public List<ItemViewModel> ItemList { get; set; }
public float X { get; set; }
public float Y { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Save(ListViewModel list)
{
return Json(list);
}
}
View:
#{
ViewBag.Title = "Home Page";
}
<script type="text/javascript">
$(function () {
var data = { ItemList: [{ Str: 'hi', Enabled: true}], X: 1, Y: 2 };
$.ajax({
url: '#Url.Action("save", "home")',
data: JSON.stringify(data),
type: 'POST',
contentType: 'application/json',
dataType: 'json',
success: function (result) {
alert(result.ItemList[0].Str);
}
});
});
</script>
Running this alerts "hi" and inside the Save action everything is correctly initialized.
And just for the record what doesn't work are Dictionaries. I've opened a ticket about the issue.
I had a similar issue, and found that for a complex object, the numeric values were getting missed. They were coming in as zeros.
i.e.
var person = {
Name: "john",
Age: 9
}
was being received by MVC controller as a Person object where the properties were being populated as Name=John and Age=0.
I then made the Age value in Javascript to be string... i.e.
var person = {
Name: "john",
Age: "9"
}
And this came through just fine...
Its because the MVC binders kind of suck. However, they do work pretty well if all JSON values come over as a string.
In JS if you do this
var myObject = {thisNumber:1.6};
myObject.thisNumber=myObject.thisNumber-.6;
It will evaluate to 1 not to 1.0
So when you sent it over to the server it will try to bind to a float of that name and it will not find it since it came over as 1 instead of 1.0. Its very lame and crazy that MS engineers did not come up with a default solution to this. I find if you string everything the bindings are smart enough to find things.
So before sending the data over run it though a stringifier that will also convert all values to strings.
All previous answers were great to point me to solution of the similar problem. I had to POST x-www-form-urlencoding instead of application/json (default option if contentType parameter is missing) to be able to pass __RequestVerificationToken and simultaneously faced with problem when object properties being in the array do not bind their values. The way to solve the issue is to understand internal work of MVC model binder.
So, basically when you need to supply verification token you are restricted with validation attribute. And you must provide the token as the parameter not as a part of the JSON-object you are sending. If you would not use ValidateAntiForgeryToken, you could get along with JSON.stringify. But if you would, you could not pass the token.
I sniffed traffic to backend when ContentType was x-www-form-urlencoding and I remarked that my array of complex objects was serialized to something like that: klo[0][Count]=233&klo[0][Blobs]=94. This array initially was a part of root object, let's say some model. It looked like that: model.klo = [{ Count: 233, Blobs: 94}, ...].
At the backend side this klo property was creating by MVC binder with the same elements count that I sent. But these elements itself did not obtain values for their properties.
SOLUTION
To deal with this I excluded klo property from the model object at the client side. In the ajax function I wrote this code:
data: $.param(model) + "&" + arrayOfObjectsToFormEncoding("klo", [{ Count: 233, Blobs: 94}, ...])
....
function arrayOfObjectsToFormEncoding (modelPropertyName, arrayOfObjects) {
var result = "";
if (arrayOfObjects && typeof arrayOfObjects == "object") {
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (obj) {
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
result += encodeURIComponent(modelPropertyName + "[" + i + "]." + p) + "=" + encodeURIComponent(obj[p]) + "&";
}
}
}
}
}
if (result[result.length - 1] == "&") {
result = result.substr(0, result.length - 1);
}
return result;
}
The function transforms array of complex object into form that is recognized by MVC-binder. The form is klo[0].Count=233&klo[0].Blobs=94.