Posting using POST from C# over https

21,697

Solution 1

see my answer to your other question. I believe your problem may not be your C# code. The web service URL accually returns a 404 with several other tools I used, but it returns the response you indicated if you leave off the trailing slash from the web service URL, so I suggest trying that.

Oddly, it doesn't seem to matter if the trailing URL is there when not doing SSL. Something strange with that web server, I guess.

Solution 2

I was battling with the exact same problem a bit earlier (although in compact framework). Here's my question and my own answer to it: Asynchronous WebRequest with POST-parameters in .NET Compact Framework

My version is asynchronous, so it's a bit more complex than what you're looking for, but the idea remains.

private string sendRequest(string url, string method, string postdata) {
    WebRequest rqst = HttpWebRequest.Create(url);

    // only needed, if you use HTTP AUTH
    //CredentialCache creds = new CredentialCache();
    //creds.Add(new Uri(url), "Basic", new NetworkCredential(this.Uname, this.Pwd));
    //rqst.Credentials = creds;
    rqst.Method = method;
    if (!String.IsNullOrEmpty(postdata)) {
        //rqst.ContentType = "application/xml";
        rqst.ContentType = "application/x-www-form-urlencoded";

        byte[] byteData = UTF8Encoding.UTF8.GetBytes(postdata);
        rqst.ContentLength = byteData.Length;
        using (Stream postStream = rqst.GetRequestStream()) {
            postStream.Write(byteData, 0, byteData.Length);
            postStream.Close();
        }
    }
    ((HttpWebRequest)rqst).KeepAlive = false;
    StreamReader rsps = new StreamReader(rqst.GetResponse().GetResponseStream());
    string strRsps = rsps.ReadToEnd();
    return strRsps;

}
Share:
21,697
Martin Marconcini
Author by

Martin Marconcini

Android developer (Kotlin/Java) and some Flutter (newbie). Did iOS (Swift) for a while, not really up to date with the latest Swift. I'm very interested in doing Rust, but I haven't found a chance to properly learn it and nobody will pay me to do it so... here we are :) I haven't done Objective-C since before ARC. I haven't done C#.NET since .NET 3.5 in 2011. I occasionally use Windows for gaming. I mainly use Linux for everything else (and macOS when I have no choice, which is sometimes the case in some corporate environments). Note to Recruiters: Please don't make me offers that are not 100% remote friendly; I've been working from home since 2001 and I expect to continue to do so, pandemic or not. Coming to an office every now and then or once a week is fine, but it should not be the norm; as a developer, the distractions are too many. I disagree with StackOverflow discontinuing JOBS/Developer Story, so I may not be as active as before on this site.

Updated on July 09, 2022

Comments

  • Martin Marconcini
    Martin Marconcini almost 2 years

    After wasting two days with this question (and trying to make it work), I've decided to take a step back and ask a more basic question, because apparently there's something I don't know or I'm doing wrong.

    The requirements are simple, I need to make an HTTP post (passing a few values) over https from C#.

    The website (if given the appropriate values) will return some simple html and a response code. (i'll show these later).

    It's really that simple. The "webservice" works. I have a php sample that works and successfully connects to it. I also have a Dephi "demo" application (with source code) that also works. And finally I have the demo application (binary) from the company that has the "service", that also works of course.

    But I need to do it through C#. That that sounds so simple, it is not working.

    For testing purposes I've created a simple console app and a simple connect method. I've tried like 7 different ways to create an HTTP request, all more or less the same thing, different implementation (Using WebClient, using HttpWebRequest, etc).

    Every method works, except when the URI begins with 'https'.

    I get a webexception saying that the remote server returned 404. I've installed Fiddler (as suggested by a SO user), and investigated a little bit the traffic. The 404 is because I am passing something wrong, because as I mentioned later, the 'service' works. I'll talk about the fiddler results later.

    The URL where I have to POST the data is: https://servicios.mensario.com/enviomasivo/apip/

    And this is the POST data: (the values are fakes)

    usuario=SomeUser&clave=SomePassword&nserie=01234567890123456789&version=01010000&operacion=220

    The server might return a two/three lines response (sorry about the spanish, but the company is from Spain). Here's a sample of a possible response:

    HTTP/1.1 200 OK
    Content-Type: text/plain
    
    01010000 100 BIEN
    998
    

    And here's another

    HTTP/1.1 200 OK
    Content-Type: text/plain
    
    01010000 20 AUTENTIFICACION NEGATIVA
    Ha habido un problema en la identificación ante el servidor. Corrija sus datos de autentificacion.
    

    The 1st one means OK, and the 2nd one is Auth Failure.

    As you can see the task is quite easy, only it doesn't work. If I use fiddler, I see that there's some sort of SSL stuff going on in the connection and then everything works fine. However, as far as I've read, .NET handles all that stuff for us (yes, i've added the callback to always validate invalid certs). I don't understand what I'm doing wrong. I can post/email the code, but what I'd like to know is very simple:

    How can you make a POST over SSL using C# and a "simple" HttpWebRequest and later have the response in a string/array/Whatever for processing?

    Trust me when I say I've been googling and Stackoverflowing for two days. I don't have any sort of proxy. The connection passes through my router. Standard ports. Nothing fancy. My Machine is inside a VMWare virtual machine and is Windows Vista, but given that the sample applications (php, delphi, binary) all work without an issue, I cannot see that as a problem).

    The different samples (sans the binary) are available here if anyone wants to take a look at them.

    I'd appreciate any help. If anyone wants to try with a "real" username, I have a demo user and I could pass you the user/pass for testing purposes. I only have one demo user (the one they gave me) and that's why I'm not pasting it here. I don't want to flood the user with tests ;)

    I've tried (within the samples) using UTF8 and ASCII, but that didn't change anything.

    I am 100% positive that there's something I have to do with SSL and I am not doing it because I don't know about it.

    Thanks in advance.

    Martín.

  • Martin Marconcini
    Martin Marconcini about 15 years
    Hi Tommi, thanks for the sample. Unfortunately it doesn't seem to be working for me either. There are two typos in your code (you use 'req' when you create the StreamReader and i think its rqst? And then the streamIn i think is rsps (near the end). Despite that, I still get a 404 in that line: StreamReader rsps = new StreamReader(req.GetResponse().GetResponseStream()); Question: If I don't want to use Credentials, can I skip that? I did it but it didn't work. This service doesn't req. user/pass
  • Tommi Forsström
    Tommi Forsström about 15 years
    Geez, sorry about the typos. I'll fix them in the answer right away. If it's 404 you're getting, then the problem is not in the code, you're just sending the wrong url. Put some breakpoints in the code sending the request and double-triple check that the url you're providing the Uri-constructor is valid. And yeah, of course you can skip the Credentials-part, I'll comment that out!
  • Tommi Forsström
    Tommi Forsström about 15 years
    Oh, and also, I need to change the content-type to "application/x-www-form-urlencoded" as you're sending regular POST params. In my case I was sending XML in the post params field and it mandated that content-type.
  • Martin Marconcini
    Martin Marconcini about 15 years
    Erv, that was it! Thanks a lot. (And thanks to the other posters for the samples, I will surely use a mix of all these. You're my hero, as I've stated in the other question. :)
  • Martin Marconcini
    Martin Marconcini about 15 years
    Moral Of the story: Always tripple check what "other developers" tell you. (The web server programmer insisted that the URL had the slash, and I believed him). :S
  • Martin Marconcini
    Martin Marconcini about 15 years
    Thanks Tommi, it was, as you also indicated, a problem with the URL (having an ending slash). :) Thanks for the code :) I will be surely using it.
  • Tommi Forsström
    Tommi Forsström about 15 years
    I recommend checking the asynchronous version found in the link provided in my answer. When sending (potentially sluggish) web requests, it's always a good thing to have the main thread nice and responsive while the data is being retrieved.
  • Martin Marconcini
    Martin Marconcini almost 14 years
    Thanks for the response Jorge, we’ve already fixed the issue. The problem was that the mensario url had a “/“ at the end, which was incorrect.
  • funsukvangdu
    funsukvangdu over 11 years
    Hi all kindly confirm is it means if i want to do https communication all other codes will be same and only diffrence will be i need to add https in url instead of http