¿Devuelve una cadena JSON explícitamente desde Asp.net WEBAPI?

85

En algunos casos tengo NewtonSoft JSON.NET y en mi controlador solo devuelvo el Jobject de mi controlador y todo está bien.

Pero tengo un caso en el que obtengo un JSON sin formato de otro servicio y necesito devolverlo desde mi webAPI. En este contexto, no puedo usar NewtonSOft, pero si pudiera, crearía un JOBJECT a partir de la cadena (que parece una sobrecarga de procesamiento innecesaria) y lo devolvería y todo estaría bien en el mundo.

Sin embargo, quiero devolver esto simplemente, pero si devuelvo la cadena, entonces el cliente recibe un contenedor JSON con mi contexto como una cadena codificada.

¿Cómo puedo devolver explícitamente un JSON desde mi método de controlador WebAPI?

klumsy
fuente

Respuestas:

197

Hay algunas alternativas. La más simple es hacer que su método devuelva a HttpResponseMessage, y cree esa respuesta con a StringContentbasado en su cadena, algo similar al código siguiente:

public HttpResponseMessage Get()
{
    string yourJson = GetJsonFromSomewhere();
    var response = this.Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(yourJson, Encoding.UTF8, "application/json");
    return response;
}

Y verificando una cadena JSON nula o vacía

public HttpResponseMessage Get()
{
    string yourJson = GetJsonFromSomewhere();
    if (!string.IsNullOrEmpty(yourJson))
    {
        var response = this.Request.CreateResponse(HttpStatusCode.OK);
        response.Content = new StringContent(yourJson, Encoding.UTF8, "application/json");
        return response;
    }
    throw new HttpResponseException(HttpStatusCode.NotFound);
}
carlosfigueira
fuente
4
Excelente. Estaba creando una cadena JSON y devolviéndola como una cadena, pero eso introdujo un extra inevitable "alrededor del resultado. Esto debería solucionarlo."
dumbledad
1
Esto es molesto. Tienes que crear el HttpResponseMessage responsey luego asignarlo StringContenta la .Contentpropiedad. No funciona si asigna StringContent en el Constructor.
Suamere
15

Aquí está la solución de @carlosfigueira adaptada para usar la interfaz IHttpActionResult que se introdujo con WebApi2:

public IHttpActionResult Get()
{
    string yourJson = GetJsonFromSomewhere();
    if (string.IsNullOrEmpty(yourJson)){
        return NotFound();
    }
    var response = this.Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(yourJson, Encoding.UTF8, "application/json");
    return ResponseMessage(response);
}
Jpsy
fuente
2

Si desea devolver específicamente ese JSON solo, sin utilizar las funciones de WebAPI (como permitir XML), siempre puede escribir directamente en la salida. Suponiendo que está alojando esto con ASP.NET, tiene acceso al Responseobjeto, por lo que puede escribirlo de esa manera como una cadena, entonces no necesita devolver nada de su método; ya ha escrito el texto de respuesta al flujo de salida.

Joe Enos
fuente
1

ejemplo de muestra para devolver datos json del método GET de la api web

[HttpGet]
public IActionResult Get()
{
            return Content("{\"firstName\": \"John\",  \"lastName\": \"Doe\", \"lastUpdateTimeStamp\": \"2018-07-30T18:25:43.511Z\",  \"nextUpdateTimeStamp\": \"2018-08-30T18:25:43.511Z\");
}
Muni Chittem
fuente
1
¿De dónde proviene el contenido? un nombre completo o una declaración de "uso" sería útil.
granadaCoder
0

estos también funcionan:

[HttpGet]
[Route("RequestXXX")]
public ActionResult RequestXXX()
{
    string error = "";
    try{
        _session.RequestXXX();
    }
    catch(Exception e)
    {
        error = e.Message;
    }
    return new JsonResult(new { error=error, explanation="An error happened"});
}

[HttpGet]
[Route("RequestXXX")]
public ActionResult RequestXXX()
{
    string error = "";
    try{
        _session.RequestXXX();
    }
    catch(Exception e)
    {
        error = e.Message;
    }
    return new JsonResult(error);
}
eci
fuente
0

Esto me funciona en .NET Core 3.1.

private async Task<ContentResult> ChannelCosmicRaysAsync(HttpRequestMessage request)
{
    // client is HttpClient
    using var response = await client.SendAsync(request).ConfigureAwait(false); 

    var responseContentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

    Response.StatusCode = (int)response.StatusCode;
    return Content(responseContentString, "application/json");
}
public Task<ContentResult> X()
{
    var request = new HttpRequestMessage(HttpMethod.Post, url);
    (...)

    return ChannelCosmicRaysAsync(request);
}

ContentResult es Microsoft.AspNetCore.Mvc.ContentResult .

Tenga en cuenta que esto no canaliza los encabezados, pero en mi caso esto es lo que necesito.

tymtam
fuente