Reputation: 934
I have a post controller in an MVC app returning this response:
return new HttpResponseMessage(HttpStatusCode.Accepted)
{
Content = new StringContent("test")
};
When I hit the post URL with this code:
using (WebClient client = new WebClient())
{
string result = client.UploadString(url, content);
}
result contains this response:
StatusCode: 202, ReasonPhrase: 'Accepted', Version: 1.1, Content: System.Net.Http.StringContent, Headers: { Content-Type: text/plain; charset=utf-8 }
Why isn't "test" appearing after Content:?
Thanks!
Upvotes: 2
Views: 1576
Reputation: 31312
You should not return HttpResponseMessage
from ASP.NET MVC action. In this case you'll get messy response like this:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRHJvcGJveFxwcm9nXFN0YWNrT3ZlcmZsb3dcZG90TmV0XE12Y0FwcGxpY2F0aW9u?=
X-Powered-By: ASP.NET
Date: Sun, 04 Feb 2018 10:18:38 GMT
Content-Length: 154
StatusCode: 202, ReasonPhrase: 'Accepted', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Content-Type: text/plain; charset=utf-8
}
As you see, you actually get 200 HTTP response with HttpResponseMessage
details in response body. This messy body content is what you deserialize into result
variable.
ASP.NET MVC actions should return an instance of the class derived from System.Web.Mvc.ActionResult
. Unfortunately, there is no built-in action result that allows setting both return status code and body content.
There is ContentResult
class that allows to set return string content with status code of 200. There is also HttpStatusCodeResult
that allows setting arbitrary status code but the response body will be empty.
But you could implement your custom action result with settable status code and response body. For simplicity, you could base it on ContentResult
class. Here is a sample:
public class ContentResultEx : ContentResult
{
private readonly HttpStatusCode statusCode;
public ContentResultEx(HttpStatusCode statusCode, string message)
{
this.statusCode = statusCode;
Content = message;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
base.ExecuteResult(context);
HttpResponseBase response = context.HttpContext.Response;
response.StatusCode = (int)statusCode;
}
}
The action would look like:
public ActionResult SomeAction()
{
return new ContentResultEx(HttpStatusCode.Accepted, "test");
}
Another possible fix is to change your controller from MVC to WEB API controller. To make this - just change base class of controller from System.Web.Mvc.Controller
to System.Web.Http.ApiController
. In this case you could return HttpResponseMessage
as in your answer.
In both cases you will get correct HTTP response with 202 status code and string in the body:
HTTP/1.1 202 Accepted
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRHJvcGJveFxwcm9nXFN0YWNrT3ZlcmZsb3dcZG90TmV0XE12Y0FwcGxpY2F0aW9u?=
X-Powered-By: ASP.NET
Date: Sun, 04 Feb 2018 10:35:24 GMT
Content-Length: 4
test
Upvotes: 1