Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Controller POST action returning simple string does not respect the request Accept header for text/plain? #7811

Closed
zijianhuang opened this issue May 22, 2018 · 5 comments

Comments

@zijianhuang
Copy link

zijianhuang commented May 22, 2018

Bug:

While the GET action respects the request Accept header for text/plain or application/json, the POST action always return JSON data which is a string quoted by double quotes, regardless of the Accept header.

Steps to reproduce :

Controller Action with ControllerBase or Controller:

        [HttpPost]
        [Route("Tuple3")]
        public string PostTuple3([FromBody] Tuple<string, string, int> tuple)
        {
            return tuple.Item1;
        }

Client:

        public string PostTuple3(System.Tuple<string, string, int> tuple)
        {
			this.client.DefaultRequestHeaders
			  .Accept
			  .Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/plain"));
			var requestUri = new Uri(this.baseUri, "api/Tuple/Tuple3");
            using (var requestWriter = new System.IO.StringWriter())
            {
            var requestSerializer = JsonSerializer.Create();
            requestSerializer.Serialize(requestWriter, tuple);
            var content = new StringContent(requestWriter.ToString(), System.Text.Encoding.UTF8, "application/json");
            var responseMessage = this.client.PostAsync(requestUri, content).Result;
            responseMessage.EnsureSuccessStatusCode();
            var stream = responseMessage.Content.ReadAsStreamAsync().Result;
            using (System.IO.StreamReader streamReader = new System.IO.StreamReader(stream))
            {
            return streamReader.ReadToEnd();;
            }
            }
        }
        
        [Fact]
        public void TestPostTuple3()
        {
            var r = api.PostTuple3(new Tuple<string, string, int>("some", "", 3));
            Assert.Equal("some", r);
        }

Result:

Message: Assert.Equal() Failure
          ↓ (pos 0)
Expected: some
Actual:   "some"
          ↑ (pos 0)

Description of the problem:

If the client want string, it is good just to give string, rather than JSON string with double quotes.

Version of Microsoft.AspNetCore.All: 2.0.6

@rynowak
Copy link
Member

rynowak commented May 22, 2018

If the client want string, it is good just to give string, rather than JSON string with double quotes.

If you have text that you want to return verbatim from an API, then I would recommend using return Content(...) and specifying the content type there.

The rationale is that if you already have text, and you just want to return it, you've already made a decision about what the content type is when you encoded it.

@zijianhuang
Copy link
Author

zijianhuang commented May 22, 2018

@rynowak . The design of the Web API (ASP.NET or .NET Core) is to enable application developers to write API codes rather than "return Content(...)" which is a clumsy workaround.

I would expect the .NET Core team to fix this, so to be consistent with the behavior of the GET action.

@rynowak
Copy link
Member

rynowak commented May 22, 2018

Can you please provide a repo application that demonstrates the problem?

The behavior you describe for your code sample is intended. If you return an object from an action method, it will be serialized by formatters, in this case the JSON formatter.

@zijianhuang
Copy link
Author

@rynowak, this point is, as mentioned in the OP, with a GET action, the response is plain text by default, not a JSON string object. And this is apparently by design, as suggested by the .NET Core team at #4945

Ah, I have just realized that you @rynowak were the guy who had answered in the other thread.

Do you agree that GET and POST actions should consistently return plain text by default when the function prototype has the return type is string?

If yes, I shall provide a simple repo application that demonstrates the problem.

@zijianhuang
Copy link
Author

Just found out in my client somewhere, I had the accept header set to application/json first, so .net core just responds according to the first accept header. So it is confirmed that GET and POST actions should consistently return plain text by default .

Thanks. Case closed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants