Bug 19529 - Missing Content-Type when issuing a Post request using System.Net.WebClient
Summary: Missing Content-Type when issuing a Post request using System.Net.WebClient
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 7.0.7
Hardware: All All
: High major
Target Milestone: Untriaged
Assignee: marcos.henrich
URL:
Depends on:
Blocks:
 
Reported: 2014-05-05 12:43 UTC by Soroush Falahati
Modified: 2014-10-28 14:27 UTC (History)
6 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Soroush Falahati 2014-05-05 12:43:52 UTC
Title said it all. When using UploadValuesTaskAsync() method from System.Net.WebClient to send a post request, it forget to add "Content-Type: application/x-www-form-urlencoded" header to the request.

I am not sure if this happens always or only in special cases, so here is my code.

Please note that I tested same code on Windows using .Net and it worked as expected. But on iPhone (I only tested on simulator) it failed. Confirmed with Fiddler2 and Charles.

     var client = new WebClient();
     NameValueCollection reqParams = new NameValueCollection
                                      {
                                          { "POSTNAME", "POSTVALUE" },
                                      };
     var response = await client.UploadValuesTaskAsync("http://example.com/mypage.jsp?Page=X&isOk=false", reqParams);

Adding

     client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

Before UploadValuesTaskAsync() will solve the problem for now.
Comment 1 Rolf Bjarne Kvinge [MSFT] 2014-05-05 13:05:12 UTC
Can you try 7.2.1 from the stable channel to see if that works better? There have been substantial changes in this area since 7.0.7.
Comment 2 Alexander Schmidt 2014-09-11 08:57:28 UTC
This bug is still there. I'm using latest stable Version and I try this on iOS-side:

using (var client = new WebClient())
{                
    parameters.DefaultHttpHeaders.Keys.ToList().ForEach(k => client.Headers.Add(k, parameters.DefaultHttpHeaders[k]));
    try
    {                    
        await client.UploadFileTaskAsync(new Uri(url), Filename);
        taskResult = true;
    }
    catch (Exception ex)
    {
        Logger.LogException(ex);
    }
}

This code on server-side:

[HttpPost]
public async Task<bool> UploadFile(string userName)
{
    var request = Request;            
    if (!request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }
    var root = HttpContext.Current.Server.MapPath("~/uploads");    
    var provider = new MultipartFormDataStreamProvider(root);
    var task = await request.Content.ReadAsMultipartAsync(provider).ContinueWith(
        o =>
        {
            var result = provider.FileData.Count > 0;            
            return result;
        });
    return task;
}

will fail. If I check the headers of the request this is the result:

{Method: POST, RequestUri: 'http://sample.url.com/param', Version: 1.1, Content: System.Web.Http.WebHost.HttpControllerHandler+LazyStreamContent, Headers:
{
  Connection: Keep-Alive
  Expect: 100-continue
  Host: sample.urlcom
  Max-Forwards: 10
  token: AnVLJMq20Y45Psj0wdlz
  culture: en-US
  X-LiveUpgrade: 1
  X-ARR-LOG-ID: 448590e5-4b92-47cf-9c49-675640a610ed
  DISGUISED-HOST: sample.urlcom
  X-SITE-DEPLOYMENT-ID: racety-svc
  X-Original-URL: /api/write/save/46bedc11-fa04-4d32-83cd-970caa44e9fd/sprinter/49zNqQZhGtUMOeVYZSWP1DWBV7I=/true
  X-Forwarded-For: 178.24.97.61:52746
  Content-Length: 3367
}}

If I use the same logic with the WebClient-version from .NET-Framework 4.5.1 it adds Content-Type as follows:

{Method: POST, RequestUri: 'http://sample.url.com/param', Version: 1.1, Content: System.Web.Http.WebHost.HttpControllerHandler+LazyStreamContent, Headers:
{
  Connection: Keep-Alive
  Expect: 100-continue
  Host: sample.urlcom
  Max-Forwards: 10
  token: AnVLJMq20Y45Psj0wdlz
  culture: en-US
  X-LiveUpgrade: 1
  X-ARR-LOG-ID: 448590e5-4b92-47cf-9c49-675640a610ed
  DISGUISED-HOST: sample.urlcom
  X-SITE-DEPLOYMENT-ID: racety-svc
  X-Original-URL: /api/write/save/46bedc11-fa04-4d32-83cd-970caa44e9fd/sprinter/49zNqQZhGtUMOeVYZSWP1DWBV7I=/true
  X-Forwarded-For: 178.24.97.61:52746
  Content-Length: 3367
  Content-Type: multipart/form-data; boundary=---------------------8d19be799a98f85
}}

This issue is very urgent because I cannot send files to my Web API right now.

Alex
Comment 3 Rolf Bjarne Kvinge [MSFT] 2014-09-11 08:59:50 UTC
Martin, can you have a look?
Comment 4 Alexander Schmidt 2014-09-16 10:25:43 UTC
Can you please provide some update on this. I'm thinking of generating a manual workaround and need to know if it's worth the time. 

Thx, Alex
Comment 5 Soroush Falahati 2014-09-17 02:11:38 UTC
I already suggested a workaround; you can simply use this line of code before calling "UploadFileTaskAsync". It should work as expected.

client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
Comment 6 Soroush Falahati 2014-09-17 02:12:54 UTC
Or in your case, 
client.Headers.Add("Content-Type", "multipart/form-data");
Comment 7 Alexander Schmidt 2014-09-20 13:18:55 UTC
Hi Soroush, lets take by side that this is a kind of funny answer to me. I want to explain you that:

- I pay liek 3.000 $ per year for this product.
- I expect the libs which are ported by MS to work the same way as they do in the original framework.
- I don't want to crete workarounds for a bug you have in your lib.
- It is a bug when you call a method UploadFile... and don't take care of the rest.

The problem is not solved by a simple

client.Headers.Add("Content-Type", "multipart/form-data");

because when you then check:

if (!request.Content.IsMimeMultipartContent())
{
    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}

on server side, it'll throw the exception. This is because you have to take case of the freakin boundaries when you use multipart... Thats where the name "multipart" comes from. I have checked this and tried to implement those "---"->wrappers in my code but I guess there is a lot of logic in encoding.

So: Your method UploadFileTaskAsync is completely useless for sending files over HTTP. What can I expect from Xamarin now?

Alex
Comment 8 Soroush Falahati 2014-09-20 21:53:36 UTC
Hi Alex,

I am the original reporter of the bug, not a member of Xamarin team :D
Just wanted to help you solve your problem for now since this may take a while for them to fix it.
Comment 9 Alexander Schmidt 2014-09-21 13:28:25 UTC
@Soroush: Oh sh...! Thanks man! Sorry for not wanting your solution ;-).
@Xamarin: SORRY!!!!! :-| 

I think, I'm a little bit nervous currently.
Comment 10 marcos.henrich 2014-09-23 05:22:22 UTC
Hi Soroush, Alexander,

Thank you for the detailed bug reports.

Soroush the issue you reported was fixed by:
https://github.com/mono/mono/commit/d56c28373b2620af2a656d9d87ad2e2955d9cc8c

Alexander the following pull request fixes the issue:
https://github.com/mono/mono/pull/1298

Once the PR is merged I will ask for the changes to be included on the next release.
Comment 11 Alexander Schmidt 2014-10-12 05:42:29 UTC
Hi Marcos,

thanks for reporting the state so quick! I will wait until the change is merged for testing because due to restriction in our development process we are not using pre-versions. Hope this is ok. 

Thanks, Alex
Comment 12 marcos.henrich 2014-10-28 14:27:07 UTC
Fixed in master 36c9c006bc170a6c29ae4cbfe6f2b88483e9786b.
https://github.com/mono/mono/commit/36c9c006bc170a6c29ae4cbfe6f2b88483e9786b