Gertsen Gertsen - 7 months ago 14
Javascript Question

Web api 2 JSON output with named object

I have an ApiController, with the following action:

[HttpGet]
public HttpResponseMessage SearchPersons(string data)
{
if (!_isAuthenticated) { return Request.CreateResponse(HttpStatusCode.Unauthorized); }

var results = new List<PersonSearchResult>();
results.Add(new PersonSearchResult() { Name = "Mr. test", Sex = "male", Married = false });
results.Add(new PersonSearchResult() { Name = "Mrs. test", Sex = "female", Married = true });
results.Add(new PersonSearchResult() { Name = "Dr. test", Sex = "female", Married = false });

return Request.CreateResponse(HttpStatusCode.OK, results, Request.GetConfiguration());
}


If authorized, it returns a list of PeopleSearchResults, and it looks like this:

[
{
"name": "Mr. test",
"sex": "male",
"married": false
},
{
"name": "Mrs. test",
"sex": "female",
"married": true
},
{
"name": "Dr. test",
"sex": "female",
"married": false
}
]


But I want it to look more like this:

{
"results": [{
"name": "Mr. test",
"sex": "male",
"married": false
}, {
"name": "Mrs. test",
"sex": "female",
"married": true
}, {
"name": "Dr. test",
"sex": "female",
"married": false
}]
}


Can I achieve this?

If not, how can I loop the first result using jQuery?
For now I tried like this, but IntelliSense tells me I can't loop it, no .Count is available on "data".
So I figure the nicest solution would be to wrap it like shown in the example I want, so I can loop data.results which should then have a .Count.

// search button action assignment:
$("#search-button").click(function () {
var search = $("#search-input").val();
if (search.trim() != "") {
var ajax = $.ajax({
dataType: "json",
url: "/api/search/SearchPersons/" + search
});

ajax.done(function (data) {
console.log("Done!");
console.log(data);
});

ajax.fail(function (data) {
console.log("Fail!");
console.log(data);
});

} else {
console.log("Empty search input value.");
$("#search-input").focus();
}
});

Answer

Can I achieve this?

Of course that you can. Start by writing a view model to reflect the required structure:

public class MyViewModel
{
    public List<PersonSearchResult> Results { get; set; }
}

and then return this view model instead of the original list:

var model = new MyViewModel();
model.Results = results;

return Request.CreateResponse(HttpStatusCode.OK, model, Request.GetConfiguration());

If not, how can I loop the first result using jQuery? For now I tried like this, but IntelliSense tells me I can't loop it, no .Count is available on "data".

.Count is a .NET property on the ICollection<T> class. In a javascript array, the corresponding property that you are looking for is called .length. So just make sure that if you want to loop over the returned collection in javascript, you are using the correct javascript property:

ajax.done(function (data) {
    for (var i = 0; i < data.length; i++) {
        var item = data[i];
        console.log(item.name);
        console.log(item.sex);
        console.log(item.married);
    }
});

So I figure the nicest solution would be to wrap it like shown in the example I want, so I can loop data.results which should then have a .Count.

Oh, no, data.results will be exactly the same array as if you haven't wrapped it in a view model. You still would have need to use the correct javascript property in order to loop over it:

ajax.done(function (data) {
    for (var i = 0; i < data.results.length; i++) {
        var item = data.results[i];
        console.log(item.name);
        console.log(item.sex);
        console.log(item.married);
    }
});

Here's a good overview of how arrays work in javascript that I would recommend you reading through.