Reputation: 93
I am creating a PCL within Xamarin that is using the Microsoft.Net.Http Nuget package for a HttpClient class. I use the HttpClient to post an audio file to a web API. This has worked well for me up to this point, but now I am having troubles while trying to get the file to be streamed to the API. The API says in its documentation to add set a "Transfer-encoding" header to be "chunked" in order for streaming of the file to be accepted. I can't add this header manually the way I have with other headers, instead a set it from a property of HttpClient. The problem is that when I call HttpClient.PostAsync(), it throws an exception because the SendChunk property of a HttpWebRequest is not True. I'm assuming that the HttpWebRequest object is creating by HttpClient, but I don't know how I can set the SendChunk property to True. When I create a HttpWebRequest object by itself, the SendChunk property is not accessible even though it is a public property. I am guessing that it has something to do with being a PCL, but the SeundChunk property does show up in the Microsoft.Net.Http Assembly.
In short, I need to get the header "Transfer-encoding : chunked" into my HttpClient headers, but can't. How can I add this header while certain properties are unavailable because I am working in a PCL?
public async Task<string> PostAsync(string url, Stream content, Dictionary<string,string> requestHeaders, Dictionary<string,string> contentHeaders)
{
var httpClient = new System.Net.Http.HttpClient();
var httpContent = new System.Net.Http.StreamContent(content);
httpClient.Timeout = TimeSpan.FromSeconds(20);
httpClient.DefaultRequestHeaders.TransferEncodingChunked = true;
if (requestHeaders != null)
{
foreach (var headerName in requestHeaders.Keys)
{
httpClient.DefaultRequestHeaders.Add(headerName, requestHeaders[headerName]);
}
}
if (contentHeaders != null)
{
foreach (var headerName in contentHeaders.Keys)
{
httpContent.Headers.Add(headerName, contentHeaders[headerName]);
}
}
HttpResponseMessage response = null;
try
{
response = await httpClient.PostAsync(url, httpContent);
}
EDIT:
I've update my code to look like this
HttpClientHandler handler = new HttpClientHandler();
System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient(handler);
httpClient.DefaultRequestHeaders.TransferEncodingChunked = true;
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
var httpContent = new System.Net.Http.StreamContent(content);
request.Content = httpContent;
if (handler.SupportsTransferEncodingChunked())
{
request.Headers.TransferEncodingChunked = true;
}
HttpResponseMessage response = null;
response = await httpClient.SendAsync(request);
SendAsync throws an exception saying "System.Net.ProtocolViolationException: SendChunked should be true". I modeled my code after this post http://blogs.msdn.com/b/bclteam/archive/2013/02/18/portable-httpclient-for-net-framework-and-windows-phone.aspx.
Upvotes: 1
Views: 10346
Reputation: 4125
I found a handly library from this link on the Xamarin Forums; https://forums.xamarin.com/discussion/25274/httpclient-in-pcl
There is a Nuget Package by Robert McLaws and Richard Beauchamp called PortableRest.
Its a library for consuming REST APIs from Portable Class Libraries (.NET 4.5, Silverlight 5, Windows Phone 8.x, and Windows 8.x). Designed to be partially drop-in compatible with RestSharp.
GitHub link here: https://github.com/AdvancedREI/PortableRest Nuget package here: https://www.nuget.org/packages/PortableRest
Source: https://forums.xamarin.com/discussion/25274/httpclient-in-pcl
To use this:
var client = new RestClient { BaseUrl = Constants.API_BASE_URI };
var request = new RestRequest("Token", HttpMethod.Post, ContentTypes.FormUrlEncoded);
request.AddHeader("Accept", "application/json");
request.AddParameter("grant_type", "password", ParameterEncoding.UriEncoded);
request.AddParameter("username", userEntry.Text, ParameterEncoding.UriEncoded);
request.AddParameter("password", passwordEntry.Text, ParameterEncoding.UriEncoded);
var result = await client.SendAsync<AuthToken>(request);
Upvotes: 0
Reputation: 163
I'm trying to deal with a similar situation. I've come across a couple of options that may help.
or this Rest Sharp
As a status update, I did get ModernHTTPClient to work. My solution though I had to delete the contents of my package folder, then install that nuget package, and then restore my other packages. Otherwise the solution was a simple as
var httpClient = new HttpClient(new NativeMessageHandler());
Upvotes: 1