Magpie
Magpie

Reputation: 7173

Returning anonymous types with Web API

When using MVC, returning adhoc Json was easy.

return Json(new { Message = "Hello"});

I'm looking for this functionality with the new Web API.

public HttpResponseMessage<object> Test()
{    
   return new HttpResponseMessage<object>(new { Message = "Hello" }, HttpStatusCode.OK);
}

This throws an exception as the DataContractJsonSerializer can't handle anonymous types.

I have replaced this with this JsonNetFormatter based on Json.Net. This works if I use

 public object Test()
 {
    return new { Message = "Hello" };
 }

but I don't see the point of using Web API if I'm not returning HttpResponseMessage, I would be better off sticking with vanilla MVC. If I try and use:

public HttpResponseMessage<object> Test()
{
   return new HttpResponseMessage<object>(new { Message = "Hello" }, HttpStatusCode.OK);
}

It serializes the whole HttpResponseMessage.

Can anyone guide me to a solution where I can return anonymous types within a HttpResponseMessage?

Upvotes: 87

Views: 87378

Answers (11)

Simon
Simon

Reputation: 4794

In ASP.NET Core Web API 6 you can use OK:

[HttpGet]
public async Task<IActionResult> GetSomething()
{
    return Ok(new { Message = "Hello World" });
}

Upvotes: 0

James Lawruk
James Lawruk

Reputation: 31337

You could use an ExpandoObject. (add using System.Dynamic;)

[Route("api/message")]
[HttpGet]
public object Message()
{
    dynamic expando = new ExpandoObject();
    expando.message = "Hello";
    expando.message2 = "World";
    return expando;
}

Upvotes: 5

tarun patkar
tarun patkar

Reputation: 31

public IEnumerable<object> GetList()
{
    using (var context = new  DBContext())
    {
        return context.SPersonal.Select(m =>
            new  
            {
                FirstName= m.FirstName ,
                LastName = m.LastName
            }).Take(5).ToList();               
        }
    }
}

Upvotes: 3

D.B
D.B

Reputation: 4289

In web API 2 you can use the new IHttpActionResult which is a replacement for HttpResponseMessage and then return a simple Json object: (Similiar to MVC)

public IHttpActionResult GetJson()
    {
       return Json(new { Message = "Hello"});
    }

Upvotes: 12

Luiso
Luiso

Reputation: 4113

This answer may come bit late but as of today WebApi 2 is already out and now it is easier to do what you want, you would just have to do:

public object Message()
{
    return new { Message = "hello" };
}

and along the pipeline, it will be serialized to xml or json according to client's preferences (the Accept header). Hope this helps anyone stumbling upon this question

Upvotes: 24

Francisco Goldenstein
Francisco Goldenstein

Reputation: 13767

In ASP.NET Web API 2.1 you can do it in a simpler way:

public dynamic Get(int id) 
{
     return new 
     { 
         Id = id,
         Name = "X"
     };
}

You can read more about this on https://www.strathweb.com/2014/02/dynamic-action-return-web-api-2-1/

Upvotes: 3

Subodh Pushpak
Subodh Pushpak

Reputation: 9

You can encapsulate dynamic object in returning object like

public class GenericResponse : BaseResponse
{
    public dynamic Data { get; set; }
}

and then in WebAPI; do something like:

[Route("api/MethodReturingDynamicData")]
[HttpPost]
public HttpResponseMessage MethodReturingDynamicData(RequestDTO request)
{
    HttpResponseMessage response;
    try
    {
        GenericResponse result = new GenericResponse();
        dynamic data = new ExpandoObject();
        data.Name = "Subodh";

        result.Data = data;// OR assign any dynamic data here;// 

        response = Request.CreateResponse<dynamic>(HttpStatusCode.OK, result);
    }
    catch (Exception ex)
    {
        ApplicationLogger.LogCompleteException(ex, "GetAllListMetadataForApp", "Post");
        HttpError myCustomError = new HttpError(ex.Message) { { "IsSuccess", false } };
        return Request.CreateErrorResponse(HttpStatusCode.OK, myCustomError);
    }
    return response;
}

Upvotes: 0

leojh
leojh

Reputation: 7712

You may also try:

var request = new HttpRequestMessage(HttpMethod.Post, "http://leojh.com");
var requestModel = new {User = "User", Password = "Password"};
request.Content = new ObjectContent(typeof(object), requestModel, new JsonMediaTypeFormatter());

Upvotes: 3

SeriousM
SeriousM

Reputation: 3521

you can use JsonObject for this:

dynamic json = new JsonObject();
json.Message = "Hello";
json.Value = 123;

return new HttpResponseMessage<JsonObject>(json);

Upvotes: 7

carlosfigueira
carlosfigueira

Reputation: 87228

This doesn't work in the Beta release, but it does in the latest bits (built from http://aspnetwebstack.codeplex.com), so it will likely be the way for RC. You can do

public HttpResponseMessage Get()
{
    return this.Request.CreateResponse(
        HttpStatusCode.OK,
        new { Message = "Hello", Value = 123 });
}

Upvotes: 90

Michael Edenfield
Michael Edenfield

Reputation: 28338

You should be able to get this to work if you use generics, as it will give you a "type" for your anonymous type. You can then bind the serializer to that.

public HttpResponseMessage<T> MakeResponse(T object, HttpStatusCode code)
{
    return new HttpResponseMessage<T>(object, code);
}

If there are no DataContract or DataMebmer attributes on your class, it will fall back on serializing all public properties, which should do exactly what you're looking for.

(I won't have a chance to test this until later today, let me know if something doesn't work.)

Upvotes: 2

Related Questions