Rückgabe anonymer Typen mit Web-API

74

Bei Verwendung von MVC war die Rückgabe von Ad-hoc-Json einfach.

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

Ich suche diese Funktionalität mit der neuen Web-API.

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

Dies löst eine Ausnahme aus, da DataContractJsonSerializeranonyme Typen nicht verarbeitet werden können.

Ich habe dies durch diesen JsonNetFormatter ersetzt, der auf Json.Net basiert . Das funktioniert wenn ich benutze

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

Aber ich sehe keinen Sinn darin, die Web-API zu verwenden, wenn ich nicht zurückkehre HttpResponseMessage. Ich sollte besser bei Vanilla MVC bleiben. Wenn ich versuche und benutze:

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

Es serialisiert das Ganze HttpResponseMessage.

Kann mich jemand zu einer Lösung führen, bei der ich anonyme Typen innerhalb von a zurückgeben kann HttpResponseMessage?

Elster
quelle

Antworten:

85

Dies funktioniert in der Beta-Version nicht, aber in den neuesten Versionen (erstellt von http://aspnetwebstack.codeplex.com ), sodass dies wahrscheinlich der Weg für RC sein wird. Du kannst tun

public HttpResponseMessage Get()
{
    return this.Request.CreateResponse(
        HttpStatusCode.OK,
        new { Message = "Hello", Value = 123 });
}
carlosfigueira
quelle
1
Dies scheint in der aktuellen Version nicht der Fall zu sein. Ich erhalte einen HTTP 500, wenn ich so etwas wie oben ausführe.
CodeMonkeyKing
Funktioniert gut für mich in 4.0 RTM.
Snixtor
16
Ein wichtiger Hinweis: Nur der Standard-JSON-Serializer kann die Serialisierung anonymer Objekte verarbeiten. Der Standard-XML-Serializer wird einen Fehler verursachen. Stellen Sie daher sicher, dass Sie anonyme Objekte zurückgeben, von denen Ihre Clients wissen, dass sie accept: application / json im Header senden. Browser wie Chrome neigen dazu, standardmäßig auch XML anzufordern, also nur ein Kopf hoch.
Despertar
17

Diese Antwort mag etwas spät kommen, aber ab heute WebApi 2ist sie bereits veröffentlicht und jetzt ist es einfacher zu tun, was Sie wollen. Sie müssten nur noch Folgendes tun:

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

und entlang der Pipeline, wird es serialisiert xmloder jsonnach Kundenpräferenzen (der AcceptKopf). Ich hoffe, dies hilft jedem, der über diese Frage stolpert

Luiso
quelle
@doker Welche Version von WebApi verwenden Sie, ich habe gerade diesen Code von meinem Controller mit VS 2015 und WebApi2 eingefügt
Luiso
5.2.3 und ich haben schließlich den XML-Formatierer entfernt, da die meisten zurückgegebenen Objekte ohnehin nicht in XML serialisiert würden.
Doker
@doker in deinem Fall dann, wenn du versuchst zu tun, was ich vorgeschlagen habe, was passiert? bekommt man ein Exception?
Luiso
8

In der Web-API 2 können Sie das neue IHttpActionResult verwenden, das HttpResponseMessage ersetzt, und dann ein einfaches Json-Objekt zurückgeben: (Ähnlich wie MVC)

public IHttpActionResult GetJson()
    {
       return Json(new { Message = "Hello"});
    }
DB
quelle
3
Beste Antwort für mich. Ich brauche eine Möglichkeit, schlankes JSON von Web API Action zurückzugeben, ohne zusätzliches Material an verschiedenen Orten / Assemblys zu produzieren. Klappt wunderbar! Vielen Dank.
Alexey Matveev
7

Sie können JsonObject dafür verwenden:

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

return new HttpResponseMessage<JsonObject>(json);
SeriousM
quelle
5

Sie könnten ein ExandoObject verwenden . (hinzufügen using System.Dynamic;)

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

Sie können auch versuchen:

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());
Leojh
quelle
2

Sie sollten in der Lage sein, dies zum Laufen zu bringen, wenn Sie Generika verwenden, da Sie dadurch einen "Typ" für Ihren anonymen Typ erhalten. Sie können dann den Serializer daran binden.

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

Wenn Ihre Klasse keine DataContractoder keine DataMebmerAttribute enthält, wird auf die Serialisierung aller öffentlichen Eigenschaften zurückgegriffen, die genau das tun sollten, wonach Sie suchen.

(Ich werde erst später heute die Möglichkeit haben, dies zu testen. Lassen Sie mich wissen, wenn etwas nicht funktioniert.)

Michael Edenfield
quelle
0

Sie können ein dynamisches Objekt in ein zurückgegebenes Objekt wie einkapseln

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

und dann in WebAPI; mach so etwas wie:

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