I'm currently working on a little prototype with Angular 2 and ASP.NET.
According to angular.io documentation (https://angular.io/docs/ts/latest/guide/server-communication.html) : "We shouldn't expect json() to return the heroes array directly. The server we're calling always wraps JSON results in an object with a dataproperty. We have to unwrap it to get the heroes. This is conventional web api behavior, driven by security concerns."
See this link : https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside
I built an APIController in ASP.NET to get a list of heros in JSON. Here is my code :
[DataContract]
public class Hero
{
[DataMember]
public string id { get; set; }
[DataMember]
public string name { get; set; }
public Hero(string id, string name)
{
this.id= id;
this.name = name;
}
}
public class HeroesController : ApiController
{
// GET api/<controller>
public IEnumerable<Hero> Get()
{
return new Hero[] { new Hero("1", "TEST HERO #1"),
new Hero("2", "TEST HERO #2")};
}
}
But bizzarely, my ApiController is returning me this JSON response : [{"id":"1","name":"TEST HERO #1"}, {"id":"2","name":"TEST HERO #2"}]
instead of something like : {"data": [{"id":"1","name":"TEST HERO #1"}, {"id":"2","name":"TEST HERO #2"}]}
Do you have any ideas why ASP.NET Web api doesn't follow this security advice? Or maybe I'm doing something wrong?
Thanks a lot!
MVC is returning exactly what you coded it to do. Instead, you could return an anonymous class like
return new { data = new Hero[] { new Hero(...), new Hero(...) } };
While I'm on the subject, you might want to get in the habit of using the HttpResponseMessage
pattern. There's nothing explicitly wrong with the way you are doing things, but this allows a lot of fine-grain control over the response you are returning, including things like custom error messages and cache expirations.
public HttpResponseMessage Get()
{
try
{
var result = new { data = new Hero[] { new Hero(...), new Hero(...) } };
return Request.CreateResponse(result);
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "My custom error message");
}
}