显式地从 Asp.net WEBAPI 返回 JSON 字符串?

在某些情况下,我有 NewtonSoft JSON.NET,在我的控制器中,我只是从我的控制器返回 Jobject,一切都很好。

但是我有一个案例,我从另一个服务获得一些原始的 JSON,并且需要从我的 webAPI 返回它。在这种情况下,我不能使用 NewtonSoft,但如果可以的话,我会从字符串中创建一个 JOBJECT (这似乎是不必要的处理开销) ,然后返回这个 JOBJECT,这样就万事大吉了。

但是,我想简单地返回它,但是如果我返回字符串,那么客户端将收到一个 JSON 包装器,其中包含我的上下文作为编码字符串。

如何从 WebAPI 控制器方法显式返回 JSON?

104847 次浏览

If you specifically want to return that JSON only, without using WebAPI features (like allowing XML), you can always write directly to the output. Assuming you're hosting this with ASP.NET, you have access to the Response object, so you can write it out that way as a string, then you don't need to actually return anything from your method - you've already written the response text to the output stream.

There are a few alternatives. The simplest one is to have your method return a HttpResponseMessage, and create that response with a StringContent based on your string, something similar to the code below:

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

And checking null or empty JSON string

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

Here is @carlosfigueira's solution adapted to use the IHttpActionResult Interface that was introduced with 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);
}

sample example to return json data from web api GET method

[HttpGet]
public IActionResult Get()
{
return Content("{\"firstName\": \"John\",  \"lastName\": \"Doe\", \"lastUpdateTimeStamp\": \"2018-07-30T18:25:43.511Z\",  \"nextUpdateTimeStamp\": \"2018-08-30T18:25:43.511Z\");
}

these also work:

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

This works for me in .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 is Microsoft.AspNetCore.Mvc.ContentResult.

Please note this doesn't channel headers, but in my case this is what I need.

If your controller method returns an IActionResult you can achieve this by manually setting the output formatter.

// Alternatively, if inheriting from ControllerBase you could do
// var result = Ok(jsonAsString);
var result = new OkObjectResult(jsonAsString);


var formatter = new StringOutputFormatter();
result.Formatters.Add(formatter);


formatter.SupportedMediaTypes.Clear();
formatter.SupportedMediaTypes.Add("application/json");