使用 Web API 返回匿名类型

在使用 MVC 时,返回 adhoc Json 很容易。

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

我正在通过新的 Web API 寻找这个功能。

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

这将引发异常,因为 DataContractJsonSerializer不能处理匿名类型。

我已经取代了这个基于 Json NetJsonNetFormatter。 如果我用

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

但是如果我不返回 HttpResponseMessage,我就看不到使用 Web API 的意义,我最好还是坚持使用普通的 MVC。如果我尝试使用:

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

它序列化了整个 HttpResponseMessage

有没有人能给我一个解决方案,让我可以在 HttpResponseMessage中返回匿名类型?

80220 次浏览

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.)

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 });
}

you can use JsonObject for this:

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


return new HttpResponseMessage<JsonObject>(json);

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());

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;
}

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;
}

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

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/

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