47

I have a large file which I have to send to a web api client...The data is multi part. The issue is , if the file is sent over http web request, then it is uploaded quickly on the webapi. For this request, file contents are written over the request stream directly.

Where as if the same file is sent over Httpclient (.net 4.5), the upload is slow when compared to http web request. I am using multipartformdatacontent in Httpclient post async.

So, for large files, do we have to use only web request? or is there any settings on Httpclient that makes the upload faster?

user2325247
  • 774
  • 1
  • 7
  • 18
  • 1
    HttpWebREquest models a single request. HttpClient models, well, a client--something that makes multiple requests. HttpClient is much more recent, so more likely to have up-to-date knowledge. Although, I don't know if it's specifically faster in certain areas; but certainly more recommended if you're doing anything in the WebAPI space or REST. – Peter Ritchie Mar 06 '14 at 19:28
  • 4
    HttpClient uses HttpWebRequest under the covers to actually make the HTTP request, so you should be able to get the same performance. – Darrel Miller Mar 07 '14 at 15:40
  • 1
    yes..but again the performance depends on how the content is passed through the client.. I used FileStreamContent and now I had changed to ByteArrayContent... – user2325247 Mar 09 '14 at 00:18
  • ```HttpWebRequest``` is obsolete, case closed: *SYSLIB9914: 'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.'* – NetXpert Sep 17 '22 at 02:18

3 Answers3

50

HttpClient is more like a head-less browser. It a powerfull and ideal tool if you are going to be creating many http request. For example you can set default headers and stuff. Here are the top 5 ways it differs from an HttpWebRequest which is taken from here

  1. An HttpClient instance is the place to configure extensions, set default headers, cancel outstanding requests and more.
  2. You can issue as many requests as you like through a single HttpClient instance.
  3. HttpClients are not tied to particular HTTP server or host; you can submit any HTTP request using the same HttpClient instance.
  4. You can derive from HttpClient to create specialized clients for particular sites or patterns
  5. HttpClient uses the new Task-oriented pattern for handling asynchronous requests making it dramatically easier to manage and coordinate multiple outstanding requests.
sergtk
  • 10,714
  • 15
  • 75
  • 130
Krimson
  • 7,386
  • 11
  • 60
  • 97
  • 6
    Thanks. This doesnt answer my question. I have an await on postAsync method and even that doesnt help. Am wondering how webrequest is faster when compared with httpclient? – user2325247 Mar 06 '14 at 04:53
  • 3
    Attribution is normally recommended: http://blogs.msdn.com/b/henrikn/archive/2012/02/11/httpclient-is-here.aspx – Paddy Apr 02 '14 at 10:16
  • 3
    Attribution twice in the post and another time in comments is quite funny... :-) – Giuseppe Feb 19 '15 at 16:46
  • 1
    Great answer. The first 7 words alone could solve many of the "why can't I scrape xyz.com using HttpClient?" – pim Jul 13 '16 at 13:02
  • The resource in the link uses JsonArray which does not seem to be available – KansaiRobot Jun 12 '18 at 04:30
5

I was using FileStreamContent with httpclient...But when I used ByteArrayContent, it worked fine.

I am not sure how and why this made the difference, but sending bytes over the stream is a better way rather than sending the stream

user2325247
  • 774
  • 1
  • 7
  • 18
  • Where did you get FileStreamContent? That isn't a default in-the-box HttpContent implementation. – Darrel Miller Mar 07 '14 at 15:41
  • Nope. I'm pretty sure it is not in either of those. – Darrel Miller Mar 09 '14 at 15:25
  • 1
    my bad..it is the StreamContent I was talking about. http://msdn.microsoft.com/en-us/library/system.net.http.streamcontent(v=vs.110).aspx – user2325247 Mar 10 '14 at 16:12
  • Showing code snippets in the question, and in this answer, would be helpful. I speculate that your byte array is significantly larger than the default stream buffer, and this helped httpclient send it with less overhead. – ToolmakerSteve Aug 06 '20 at 21:33
5

Perhaps you were instantiating HttpClient in a using block which could explain performance issues. E.g.

  using (var httpClient = new HttpClient() )
  {
      var result = await httpClient.GetAsync("http://example.com");
      Console.WriteLine(result.StatusCode);
  }

Here the instance of HttpClient is being disposed immediately after the request whereas it should arguably be a long lived object (E.g. the lifetime of the application).

[edit - added context]

Disposing the instance also closes the connection but leaves the socket in a waiting state for a set duration. For each execution of this code, the os will attempt to create a new socket connection, and since there is a limit to how quickly this can be completed, performance/reliability issues can arise.

Reusing the same HttpClient instance means better reuse of open sockets and more efficient use of system resources.

More info here.

mounds
  • 1,303
  • 12
  • 11
  • *CS4033: "The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing it's return type to 'Task'."* So, what does the method declaration surrounding this code look like, and what is the valid Task value that you used in the corresponding return statement? – NetXpert Sep 17 '22 at 02:20
  • @NetXpert I think you’ve missed the point. This code block is simply to illustrate how httpclient might be misused by instantiating it in a using block. Wrapping it in a method definition adds nothing of value. Also, the OP states .Net 4.5 as the target. – mounds Sep 18 '22 at 05:13
  • I think you missed the larger point: Given that the code you've given ***won't even compile,*** I think that you've completely lost the forest in the trees! It's pretty difficult, in my experience, to somehow inadvertently **mis**-use code that can't even be *used* in the first place due to not being compilable because of the errors I identified... – NetXpert Sep 21 '22 at 04:23
  • *"Also, the OP states .Net 4.5 as the target"* -- that's why I specifically added the comment *"This is not an example of **contemporary,** valid code."* -- so future readers of this post would see a note pointing out that it's not valid C# *anymore*. – NetXpert Sep 21 '22 at 04:29
  • @NetXpert The code sample compiles and runs fine. 1. Create a C# console program. target .net framework 4.5. 2. Import System.Net.Http from nuget. 3. Add an async method (E.g. public static Task DoStuff) and paste my code in its body, changing 'example.com' to the url you'd like to spam, and call it from your main method*. 4. Build it and run it. StatusCode is indeed a property of System.Net.Http.HttpResponseMessage after GetAsync is 'await'ed. * If you need help creating/calling an async method, ask a question on SO and I'm sure someone will be willing to help you. – mounds Oct 17 '22 at 11:45
  • If the code above, AS IS, "compiles and runs fine", why would I need your step 3? Bear in mind that I specifically asked you what the wrapping method looked like and what the valid return type was that should be applied in it, and you said I missed the point... You can't be taken very seriously when you say, "the code above is fine" then add "...if you do this other stuff first, (that is exactly what you asked about)" WHILE trying to claim that *I* missed the point... – NetXpert Oct 18 '22 at 15:43
  • Also, even .Net 5.0 is already deprecated, I'm certainly not going to be creating any new projects in *.Net4x* -- .Net7 is current, and I specifically identified that my comments pertain to *CONTEMPORARY* code development by current developers who may find this answer while looking for help using ```HttpClient```. Furthermore, after a lot of legwork, I already bodged together a solution for obtaining web content as a string from a single function call: https://stackoverflow.com/a/73823939/1542024 – NetXpert Oct 18 '22 at 15:50
  • @NetXpert There are multiple steps required to make any c# snippet just work. I outlined several steps (including 3) because you seem to be trying to run this code in .net7. The question is about .net 4.5, not the version of .net one would choose today. Sometimes people don't get a choice. The code is there to illustrate misuse of HttpClient and the potential performance issues that can result. IMO addional code detracts from the point. Also, try to be more polite. We're all just trying to be helpful here :) Your excessive use of italics, emojis and quotes comes off as quite aggressive IMO. – mounds Oct 18 '22 at 23:36