Web Api:推荐的返回json字符串的方法

时间:2016-11-27 19:45:13

标签: c# asp.net-web-api2

我有几个服务已经收到必须返回给客户端的json字符串(不是对象)。目前,我正在显式创建HttpResponseMessage并将其Content属性设置为服务接收的json字符串:

var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jsonUtilizadores, Encoding.UTF8, "application/json");
return response;

现在,使用新的IHttpActionResult有更好的方法吗?使用ContentOk方法最终用引号包装json字符串,这不是我想要的。

有任何反馈吗?

4 个答案:

答案 0 :(得分:10)

创建自定义实现。该框架可通过IHttpActionResult扩展。

以下内容创建自定义结果和扩展方法...

public static class JsonStringResultExtension {
   public static CustomJsonStringResult JsonString(this ApiController controller, string jsonContent, HttpStatusCode statusCode = HttpStatusCode.OK) {
        var result = new CustomJsonStringResult(controller.Request, statusCode, jsonContent);
        return result;
    }

    public class CustomJsonStringResult : IHttpActionResult {
        private string json;
        private HttpStatusCode statusCode;
        private HttpRequestMessage request;

        public CustomJsonStringResult(HttpRequestMessage httpRequestMessage, HttpStatusCode statusCode = HttpStatusCode.OK, string json = "") {
            this.request = httpRequestMessage;
            this.json = json;
            this.statusCode = statusCode;
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) {
            return Task.FromResult(Execute());
        }

        private HttpResponseMessage Execute() {
            var response = request.CreateResponse(statusCode);
            response.Content = new StringContent(json, Encoding.UTF8, "application/json");
            return response;
        }
    }
}

...然后可以应用于ApiController派生类。大大简化了之前对

的调用
return this.JsonString(jsonUtilizadores); //defaults to 200 OK

或使用所需的HTTP状态代码

return this.JsonString(jsonUtilizadores, HttpStatusCode.BadRequest);

答案 1 :(得分:4)

将您的Web Api设置为返回JSON格式:

    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        // Force to ignore Request Content Type Header and reply only JSON
        config.Formatters.Clear();
        config.Formatters.Add(new JsonMediaTypeFormatter());

        var corsAttr = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(corsAttr);
    }

然后像这样返回响应:

        [HttpGet]
    [Route("{taskId}/list")]
    public IHttpActionResult GetTaskDocuments(string taskId)
    {
        var docs = repository.getTaskDocuments(taskId);
        if (docs != null)
        {
            return Ok(docs);
        }
        else
        {
            return Ok(new ResponseStatus() { Status = Constants.RESPONSE_FAIL, Message = repository.LastErrorMsg });
        }
    }

ResponseStatus是下一个类:

 public class ResponseStatus
    {
        public string Status { get; set; }
        public string Message { get; set; }
    }

答案 2 :(得分:3)

将响应格式保留给内容协商以符合REST,客户端应该决定它想要的格式。

在您的网址API操作中,您应该返回Ok(your object),网址API会看到返回它的最佳格式。

如果您需要省略其他格式化程序,那么就像Nkosi建议的那样删除其他MediaTypeFormatter个对象。

答案 3 :(得分:1)

这是@Nkosi的回答翻译为VB.Net。

我正在构建WebAPI2后端以支持TourOfHeroes。

我想像一下我有一个“重”对象并且我不想将所有属性返回到所有视图的情况。想象一下Hero有大约30列,而Heroes.component.ts ....我只需要ID和名称。

我不想另外创建一个对象来代表每个视图,以便我可以对它们进行JSON序列化...干吗?

因此,这是@NKosi发布的2个类。不确定共享类是否必要,我只是按照@NKosi编写的实现。

Imports System.Net.Http
Imports System.Web.Http
Imports System.Net
Imports System.Threading
Imports System.Threading.Tasks

Public Class JsonStringResultExtension

    Public Shared Function JSONString(Controller As ApiController,
                                                Optional jsonContent As String = "",
                                             Optional statusCode As HttpStatusCode = HttpStatusCode.OK) As CustomJsonStringResult

        Dim result As New CustomJsonStringResult(Controller.Request, statusCode, jsonContent)
        Return result
        End Function

  End Class

    Public Class CustomJsonStringResult
        Implements IHttpActionResult

    Private json As String
    Private statusCode As HttpStatusCode
    Private request As HttpRequestMessage

    Public Sub New(httpRequestMessage As HttpRequestMessage, Optional statusCode As HttpStatusCode = HttpStatusCode.OK, Optional json As String = "")
        Me.request = httpRequestMessage
        Me.json = json
        Me.statusCode = statusCode
    End Sub

    Public Function ExecuteAsync(cancellationToken As CancellationToken) As Task(Of HttpResponseMessage) Implements IHttpActionResult.ExecuteAsync
        Return Task.FromResult(Execute())
    End Function

    Private Function Execute() As HttpResponseMessage
        Dim response = request.CreateResponse(statusCode)
        response.Content = New StringContent(json, Encoding.UTF8, "application/json")

        Return response
    End Function


End Class

我还将在webApiConfig.vb中添加以下内容,否则您将抱怨无法解析HTML

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(New MediaTypeHeaderValue("text/html"))
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(New MediaTypeHeaderValue("application/json"))

这里是支持heroes.component.js的webAPI控制器调用 就像@Luis Abreu一样,我的BO已经返回了JSON。我只想将正确格式的JSON作为字符串返回,而不是将我的BO映射到API此处的另一个类中,而仅仅是将其序列化...

 <HttpGet>
        <Route("")>
        Public Function GetAllHeroes() As CustomJsonStringResult

           'populate a list of heros however you want 
            dim ag as  new  HeroAg()
            Dim l As List(Of TOHbos.Hero) = ag.Items



            'This should be shoved down into a reusable class...ListToJSON
            Dim sb As New StringBuilder("")
            Dim first As Boolean = True
            sb.Append("[")
            For Each h As TOHbos.Hero In l

                If first = True Then
                    first = False
                Else
                    sb.Append(", ")
                End If
                 'decide which fields to include and generate a JSON document
                 h.decideWhichFieldsGetSerializedForThisView()
                sb.Append(h.JSON)
            Next
            sb.Append("]")

            Return JsonStringResultExtension.JSONString(Me, sb.ToString(), HttpStatusCode.OK)

        End Function

我遇到的下一个问题是,我是从浏览器控制台的Angular应用程序中收到此错误

 Http failure during parsing for localhost:4300/api/heroes

使用jsonLint.com,我能够确定我的JSON不太正确。我不是将键名放在双打勾中,而是将值放在单打勾中。尽管这可能是可接受的JSON,但是jsonLint抱怨,我想Angular rxjs也是如此