1

I am having a problem that many people have experienced but all of the solution that are available online are specific to their scenarios. I have tried the suggestions available but still no luck wha I have tried was:

1.) req.KeepAlive = false;
2.) req.ProtocolVersion = HttpVersion.Version10; (this solved a different exception that I was getting)

I have two methods passing XML string to the server and getting responses back the two methods are:

public string userDeviceQuery(string userID)
    {
        string query = "xml=<query>";
        query += "<appInfo>";
        query += "<appID>" + appID + "</appID>";
        query += "<appCertificate>" + appCertificate + "</appCertificate>";
        query += "</appInfo>";
        query += "<userDevicesQuery>";
        query += "<userID>";
        query += userID;
        query += "</userID>";
        query += "</userDevicesQuery>";
        query += "</query>";

        using (Stream str = req.GetRequestStream())
        {
            str.Write(System.Text.Encoding.ASCII.GetBytes(query), 0, query.Length);
        }

        WebResponse res = req.GetResponse();

        string stringResponse;
        using (StreamReader reader = new StreamReader(res.GetResponseStream()))
        {
            stringResponse = reader.ReadToEnd();
        }

        string result = parseDeviceQueryRes(stringResponse);
        return result;
    }

AND

public void logoutOfEM(string deviceName)
    {
        string lgRequest = "xml=<request>";
               lgRequest += "<appInfo>";
               lgRequest += "<appID>" + appID + "</appID>";
               lgRequest += "<appCertificate>" + appCertificate + "</appCertificate>";
               lgRequest += "</appInfo>";
               lgRequest += "<logout>";
               lgRequest += "<deviceName>";
               lgRequest += deviceName;
               lgRequest += "</deviceName>";
               lgRequest += "</logout>";
               lgRequest += "</request>";

         using (Stream str = req.GetRequestStream())
        {
            str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
        }

        WebResponse res = req.GetResponse();

        using (StreamReader reader = new StreamReader(res.GetResponseStream()))
        {
            stringResponse = reader.ReadToEnd();
        }
        string stringResponse = reader.ReadToEnd();
    }

They are both part of a class called EMAPI. I can use both methods just fine separately but if try to use them back-to-back with the same object representing EMAPI I get the exception described above. I am not sure what is causing the connection to close, I would like to be able to keep it open and close it using a de-constructor if possible.

For those who are curious this code deals with Cisco Extension Mobility API, first method queries the server to get a device you are logged in, second method logs teh user out of that device.

Thanks for the help.

laitha0
  • 4,148
  • 11
  • 33
  • 49
  • On an unrelated note I would use stringbuilder for efficient when constructed huge + strings. – Cubicle.Jockey Jul 24 '13 at 21:30
  • Can you please elaborate more, why is StringBuidler better when concatenating strings? – laitha0 Jul 24 '13 at 21:33
  • 1
    http://www.dotnetperls.com/stringbuilder-performance – Cubicle.Jockey Jul 24 '13 at 21:35
  • Did you check the connection state after the first call. It may be case that connection is closed by remote server. – indolentdeveloper Jul 24 '13 at 21:37
  • 1
    Oh wow, I have about 15 queries in my code using string, I will fix them all. That could solve the slowness that I am experiencing. Tahnks!! – laitha0 Jul 24 '13 at 21:38
  • @theusguy The connection is automatically closed after calling either method, thats why I am not able to call the second method. I am not sure why it is closing automatically. I can instantiate the EMAPI again and call the second method but there has to be a better solution – laitha0 Jul 24 '13 at 21:40

2 Answers2

2

Use a different HttpWebRequest for each method. You should not reuse the HttpWebRequest object for different requests. Check this: Can I reuse HttpWebRequest without disconnecting from the server?. Internally, .NET can decide to reuse the connection to the same server if possible, but the server can decide to close the connection after each request, even if you specify req.KeepAlive = true.

Also make sure you dispose/close your WebResponse object in your methods.

Community
  • 1
  • 1
fcuesta
  • 4,429
  • 1
  • 18
  • 13
1

I would be using the 'using' keyword around all of my IDisposables first off. Secondly looks like you are leave the StreamReaders open.

Edit

To answer you comment about using keyword.

Instead of this:

Stream str = req.GetRequestStream();
str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
str.Close();

Write it this way:

using(Stream str = req.GetRequestStream())
{
    str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
}

The using keyword will automatically handle all IDisplosable task for you.

I just noticed something your code and why I thought you weren't closing. You are calling close and then trying to ready the lines. This is a good example of why to get into the habit of using the 'using' keyword.

StreamReader reader = new StreamReader(res.GetResponseStream());
reader.Close(); //Calling CLOSE before trying to use the reader
string stringResponse = reader.ReadToEnd();

ANOTHER EDIT

public void logoutOfEM(string deviceName)
    {
        string lgRequest = "xml=<request>";
               lgRequest += "<appInfo>";
               lgRequest += "<appID>" + appID + "</appID>";
               lgRequest += "<appCertificate>" + appCertificate + "</appCertificate>";
               lgRequest += "</appInfo>";
               lgRequest += "<logout>";
               lgRequest += "<deviceName>";
               lgRequest += deviceName;
               lgRequest += "</deviceName>";
               lgRequest += "</logout>";
               lgRequest += "</request>";
     using (Stream str = req.GetRequestStream())
    {
        str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
    }

    WebResponse res = req.GetResponse();

    var response = string.Empty;
    using(StreamReader reader = new StreamReader(res.GetResponseStream()))
    {
        response = reader.ReadToEnd();
    }


}
Cubicle.Jockey
  • 3,288
  • 1
  • 19
  • 31
  • I did close all StreamReaders but that didn't help I am not sure what you are refering to " using the 'using' keyword around all of my IDisposables first off" – laitha0 Jul 24 '13 at 21:39
  • That makes since why we should be doing this, but it still did not fix the problem, I have updated my code in the question – laitha0 Jul 24 '13 at 21:48
  • In your edited question you are still calling reader.Close() the trying to use the reader after you closed it in method logoutOfEM – Cubicle.Jockey Jul 24 '13 at 21:49
  • its a different reader in both methods, i am creating a reader and closing it in both of them – laitha0 Jul 24 '13 at 21:52
  • Yes but you still not understanding. You are calling close, before doing the ReadToEnd() in the method logoutOfEM. I corrected it in my edit. – Cubicle.Jockey Jul 24 '13 at 21:54
  • I am not calling Close() anymore, i switched them to use 'using' but still same exception, and its happening at str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length); – laitha0 Jul 24 '13 at 22:00
  • I made an update to your question, had some extra calls still. Where is req defined? – Cubicle.Jockey Jul 24 '13 at 22:04
  • req is a global HttpWebRequest that gets instantiated in teh constructor – laitha0 Jul 24 '13 at 22:09
  • I would probably create a new one before each method call not create 1 on instatiation and pass that into those methods as a parameter. – Cubicle.Jockey Jul 24 '13 at 22:15
  • Yes that was the problem look at fcuesta answer. You should use a seperate HttpWebRequest for each one, I did not know that. Thanks for the help!! – laitha0 Jul 24 '13 at 22:18
  • Cool beans. Well hope you learned other stuff other than your issue. :) – Cubicle.Jockey Jul 24 '13 at 22:19
  • definitely, I am switching to use StringBuilder(), and using "using" is also important to handle disposing objects automatically, lots of lessons in one thread :) – laitha0 Jul 24 '13 at 22:30
  • :) Awesome. Take care. – Cubicle.Jockey Jul 24 '13 at 22:32