You hope you can use .ReadAsStringAsync()
on the current MVC request because perhaps you've seen something like this?
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using System.Threading.Tasks;
namespace DL.SO.UI.Web.Controllers
{
public class DashboardController : Controller
{
// In order to be able to inject the factory, you need to register in Startup.cs
// services.AddHttpClient()
// .AddRouting(...)
// .AddMvc(...);
private readonly IHttpClientFactory _httpClientFactory;
public DashboardController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<IActionResult> Index()
{
var client = _httpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
string bodyContent = await response.Content.ReadAsStringAsync();
}
return View();
}
}
}
This is how you use HttpClient
to fetch external data/resources in an app. .ReadAsStringAsync()
is off an HttpContent
, which is the property of either HttpRequestMessage
or HttpResponseMessage
. Both HttpRequestMessage
and HttpResponseMessage
are in System.Net.Http
namespace.
But now you're in the app itself! Things work a little bit differently. We don't have a response for the request yet (because we haven't done return View();
). Hence I assume the content you want to look at is the content of the request coming in?
GET request's content
When a GET request comes in, MVC will automatically bind request's query strings to action method parameters in the controller. They're also available in the Query
property off the current Request
object:
public IActionResult Index(int page = 1, int size = 15)
{
foreach (var param in Request.Query)
{
...
}
return View();
}
POST request's content
When a POST request comes in, Request.Body
might not always have the data you're looking for. It depends on the content type of the POST request.
By default when you're submitting a form, the content type of the request is form-data. MVC then will bind the inputs to your view model as the action parameter:
[HttpPost]
public async Task<IActionResult> Close(CloseReservationViewModel model)
{
Request.Form // contains all the inputs, name/value pairs
Request.Body // will be empty!
...
}
If you use jQuery
to fire POST requests without specifying the contentType
, it defaults to x-www-form-urlencoded:
@section scripts {
<script type="text/javascript">
$(function() {
$.ajax({
url: '@Url.Action("test", "dashboard", new { area = "" })',
data: {
name: 'David Liang',
location: 'Portland Oregon'
},
method: 'POST'
}).done(function (response) {
console.info(response);
});
});
</script>
}
[HttpPost]
public async Task<IActionResult> Test()
{
string body;
using (var reader = new StreamReader(Request.Body))
{
body = await reader.ReadToEndAsync();
}
return Json(body);
}

Conclusion
If you want to use HttpClient
to call external services inside your MVC app, you can utilize IHttpClientFactory
, HttpClient
from System.Net.Http
and get a HttpContent
from either the request or response without too much trouble. Then you can do ReadAsStringAsync()
off it.
If you want to peek on the request data sent from the client to your MVC app, MVC has already done so much to help you bind the data using model binding. You can also read request's body for POST requests with a StreamReader
. Just pay attention that depends on the content type, Request.Body
might not have what you expect.