Problem with encoding a character

D

David

Hi all,

I am trying to send an SMS and am having problem sending the UK Pound
symbol, £

It appears to be crashing out on the streamwriter line. The result I am
getting is...

System.Net.WebException: The request was aborted: The request was
canceled. ---> System.IO.IOException: Cannot close stream until all bytes
are written.

I have tried a number of encodings, but it appears to come through as a ? or
a square (when it doesn't crash out). What encoding should I use?

As mentioned in another message, I am using
http://www.txtlocal.co.uk/signup/ as my SMS provider.

public string SendMessage(string From, string Number, string Message)
{
string result = string.Empty;
string strPost = string.Empty;

string SMSUrl = ConfigurationManager.AppSettings["SMSUrl"];
string User = ConfigurationManager.AppSettings["SMSUser"];
string Pass = ConfigurationManager.AppSettings["SMSPass"];

Number = Number.Replace("+", string.Empty);

string TestMode = string.Empty;
try
{
if
(ConfigurationManager.AppSettings["SMSTestMode"].ToLower() == "true")
{
TestMode = "&test=1";
//Number = "998" + Number;
}
}
catch
{
}


strPost = "uname=" + User + "&pword=" + Pass + "&message=" +
Message + "&from=" + From + "&selectednums=" + Number + "&info=1" +
TestMode;

StreamWriter myWriter = null;
HttpWebRequest objRequest =
(HttpWebRequest)WebRequest.Create(SMSUrl);

//add Proxy info if required
//objRequest.Proxy = WebProxy.GetDefaultProxy();
//objRequest.Proxy.Credentials =
CredentialCache.DefaultCredentials; //uses logged on user
//objRequest.Proxy.Credentials = new
System.Net.NetworkCredential("UserName", "Password"); // Alternative -
specify the user and password to use
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
objRequest.ContentType = "application/x-www-form-urlencoded";
try
{
myWriter = new StreamWriter(objRequest.GetRequestStream());
myWriter.Write(strPost);
}
catch (Exception e)
{
return e.Message;
}
finally
{
myWriter.Close();
}

HttpWebResponse objResponse =
(HttpWebResponse)objRequest.GetResponse();
using (StreamReader sr = new
StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
return result;
}

--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
P

Peter Duniho

Hi all,

I am trying to send an SMS and am having problem sending the UK Pound
symbol, £

Looks fine here. "rossum"'s newsreader is probably simply set to assume a
different encoding than mine (your post doesn't actually describe an
encoding, so the receiving newsreader has to assume something...my
newsreader "guessed" right, his "guessed" wrong :) ).
It appears to be crashing out on the streamwriter line. The result I am
getting is...

System.Net.WebException: The request was aborted: The request was
canceled. ---> System.IO.IOException: Cannot close stream until all bytes
are written.

I don't understand this description. What is "the streamwriter line"?
The only line of code you posted that actually has the word "StreamWriter"
in it is where you create it. I don't understand why you'd get something
complaining about closing when you're just trying to create it.

I suspect that for whatever reason, your request stream is not getting the
number of bytes written to it that you advertise in the ContentLength
field. It's not entirely clear why this would be; you're passing the
string length, which if anything should cause the written content to
_exceed_ the ContentLength field (i.e. for any encoding not 8-bits per
character), and in any case I don't see why you'd get an exception until
you actually try to write to the stream.

I suppose it's possible that the Stream you get back from
GetRequestStream() is a special stream for the HttpWebRequest object that
checks the bytes written and automatically closes itself when you reach
the number of bytes you said you were going to write. But even in that
case, I'd expect the exception to happen when you write to the stream, not
when you create it.

For sure, if you use any non-8-bit encoding, you're going to have problems
with the code you posted. But whether that's directly related to the
problem you're asking about, I can't say.

If you really want help, you need to figure out a way to create and post a
concise-but-complete code example that reliably demonstrates the problem.
We have to be able to reproduce the error, and to do so in a way that
isn't dependent on your SMS infrastructure. For example, maybe you can
reproduce the error using a POST to some other web site.

As far as "what encoding should you use" goes...you should use an encoding
that can represent the characters you want to send _and_ which is
supported by the receiving end _and_ you should use it correctly (i.e. the
ContentLength needs to describe the length of the content in bytes, not
characters).

Pete
 
D

David

Hi Peter,

That code sample is a full sample, apart from the URL and sign-in details. I
am not sure what else I can show.

It is actually failing in the finally, the myWriter.Close().

I am also speaking with the SMS people to come to a solution. I have figured
that it is down to the byte length, not the character length. Basically, the
pound symbol is looking like 2 bytes instead of 1. I know this appears to be
happening, as when I change the ContentLength by adding one (+ 1), the pound
symbol goes through.

It was the text in the error message that gave me that clue and also the
stepping through and seeing it fail on the finally, without even being
caught by the catch. With the error message stating that it can't close
until all bytes are sent, it was the realisation that the pound sign £ must
be two bytes instead of one, as without the symbol, everything worked hunky
dory.

I thought the pound sign was a unicode character, but when I tried to change
it to unicode in the opening of the myWriter, it still failed.

If the SMS people come back with a solution or I work it out, I will post it
for reference.
--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
P

Peter Duniho

Hi Peter,

That code sample is a full sample, apart from the URL and sign-in
details. I
am not sure what else I can show.

Here are some links you may find helpful:
http://www.yoda.arachsys.com/csharp/complete.html
http://www.yoda.arachsys.com/csharp/incomplete.html
http://sscce.org/ (some Java-centric stuff, but mostly applicable to any
programming questions)
It is actually failing in the finally, the myWriter.Close().

As the references above will point out, part of asking a good question is
providing accurate information regarding what's failing.
I am also speaking with the SMS people to come to a solution. I have
figured
that it is down to the byte length, not the character length. Basically,
the
pound symbol is looking like 2 bytes instead of 1. I know this appears
to be
happening, as when I change the ContentLength by adding one (+ 1), the
pound
symbol goes through.

In other words, your problem very well may be caused by the problem I
noted in my previous post: that you are setting the ContentLength property
incorrectly by providing character length instead of byte length.
It was the text in the error message that gave me that clue and also the
stepping through and seeing it fail on the finally, without even being
caught by the catch. With the error message stating that it can't close
until all bytes are sent, it was the realisation that the pound sign £
must
be two bytes instead of one, as without the symbol, everything worked
hunky
dory.

I thought the pound sign was a unicode character, but when I tried to
change
it to unicode in the opening of the myWriter, it still failed.

The pound sign, in and of itself, neither is nor is not a Unicode
character. It is simply a specific glyph, referenced in some character
encodings as a specific character code. Some character encodings include
the character, some do not. If you want to represent the pound sign, you
have to use an encoding that supports that character. And yes, in some of
those encodings (the Unicode encodings, for example) the pound sign will
be more than one byte.

I don't know what you mean by "tried to change it to unicode". Change
what to Unicode? The default for StreamWriter is UTF-8 anyway. What else
was there to "change"?
If the SMS people come back with a solution or I work it out, I will
post it
for reference.

It seems to me that the immediate problem -- the exception -- is obvious:
you were not setting the ContentLength property correctly. You can fix
that problem by handling the encoding yourself (see the Encoding class) so
that you know exactly how many bytes your message will use, and then just
writing those bytes directly rather than using the StreamWriter class (for
example, as an alternative to using the Encoding class directly, write to
a MemoryStream using StreamWriter, before you need to set the
ContentLength property, and then write the bytes from the MemoryStream out
to your request Stream).

As for whether you are able to get your recipient to understand an
encoding that includes the pound sign (e.g. UTF-8, the default for
StreamWriter), that would be an issue specific to the recipient, and not
really a C#/.NET issue at all.

Pete
 
D

David

I worked it out...

I realised it was the byte length that was required rather than the string
length, as without the pound symbol, everything worked. (I did work this out
before I saw this post, but was unable to apply it immediately to test)

objRequest.ContentLength is now...
objRequest.ContentLength =
System.Text.ASCIIEncoding.UTF8.GetByteCount(strPost);

So, while it wasn't specifically encoding the string, it is getting the
correct length.

--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top