Ho scoperto un bug nel framework .NET o sto facendo qualcosa di sbagliato?non può contenere sterlina britannica in WCF?
Ecco la storia.
stavo cercando di impostare una password sul canale WCF ieri così:
channelFactory.Credentials.UserName.UserName = credentials.Username;
channelFactory.Credentials.UserName.Password = credentials.Password;
e quindi richiamare il metodo di servizio Web quando ho ottenuto questo errore:
System.ServiceModel.CommunicationException
Message=An error (The request was aborted: The request was canceled.) occurred while transmitting data over the HTTP channel.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at PocketKings.Tools.Services.PopulationManager.Client.PopulationService.IPopulationService.ResolvePopulationMember(ResolveRealmMemberQuery request)
InnerException: System.Net.WebException
Message=The request was aborted: The request was canceled.
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
InnerException: System.NotSupportedException
Message=This method is not supported by this class.
Source=System
StackTrace:
at System.Net.BasicClient.EncodingRightGetBytes(String rawString)
at System.Net.BasicClient.Lookup(HttpWebRequest httpWebRequest, ICredentials credentials)
at System.Net.BasicClient.Authenticate(String challenge, WebRequest webRequest, ICredentials credentials)
at System.Net.AuthenticationManager.Authenticate(String challenge, WebRequest request, ICredentials credentials)
at System.Net.AuthenticationState.AttemptAuthenticate(HttpWebRequest httpWebRequest, ICredentials authInfo)
at System.Net.HttpWebRequest.CheckResubmitForAuth()
at System.Net.HttpWebRequest.CheckResubmit(Exception& e)
at System.Net.HttpWebRequest.DoSubmitRequestProcessing(Exception& exception)
at System.Net.HttpWebRequest.ProcessResponse()
at System.Net.HttpWebRequest.SetResponse(CoreResponseData coreResponseData)
Così ho iniziato a guardare a questo e i registri mostrano che non riesco nemmeno ad arrivare fino al server. Si scopre che il metodo .NET framework, che genera un'eccezione (System.Net.BasicClient.EncodingRightGetBytes (String rawString)) non piace il segno della sterlina britannica (£).
ho copiato il metodo dal riflettore e ha scritto uno unit test rapido e libbra è l'unico personaggio che pretende molto come da tutte ho potuto digitare su una tastiera:
internal static byte[] EncodingRightGetBytes(string rawString)
{
byte[] bytes = Encoding.Default.GetBytes(rawString);
string strB = Encoding.Default.GetString(bytes);
if (string.Compare(rawString, strB, StringComparison.Ordinal) != 0)
{
throw ExceptionHelper.MethodNotSupportedException;
}
return bytes;
}
Questo è il mio test di unità per verificare questo metodo:
[Test]
public void test123()
{
string domain = "localhost";
string userName = "lukk";
string charactersToCheck = @"¬`!£$%^&*()_+={}[]:;@'~#<>,.?/|\";
foreach (var character in charactersToCheck.ToCharArray())
{
string internalGetPassword = character.ToString();
try
{
// begin - this assignement was copied from System.Net.BasicClient.Lookup method
byte[] inArray = EncodingRightGetBytes(
(!string.IsNullOrEmpty(domain) ? (domain + @"\") : "")
+ userName
+ ":"
+ internalGetPassword);
//end
}
catch (Exception ex)
{
Console.WriteLine(string.Format("this character is bad: {0}", internalGetPassword));
}
}
}
Come si può vedere EncodingRightGetBytes confronta due stringhe e sono differenti se la stringa originale (rawString) contiene sterlina inglese.
EncodingRightGetBytes funziona bene quando si sostituisce la con ...
Googling questo il nome del metodo riporta pochissimi link, uno dei quali è questo “Encoding.Default.” “Encoding.UTF8.”: http://support.microsoft.com/kb/943511
Sto usando VS 2010 con un progetto asp.net impostato per utilizzare .net 3.5.
Quindi sarebbe un bug nel framework .NET o sto facendo qualcosa di sbagliato?
Edit: Quando interrogo l'Encoding.Default nella finestra immediata durante l'esecuzione il mio test ottengo questo:
?Encoding.Default
{System.Text.SBCSCodePageEncoding}
[System.Text.SBCSCodePageEncoding]: {System.Text.SBCSCodePageEncoding}
BodyName: "iso-8859-2"
CodePage: 1250
dataItem: {System.Globalization.CodePageDataItem}
decoderFallback: {System.Text.InternalDecoderBestFitFallback}
DecoderFallback: {System.Text.InternalDecoderBestFitFallback}
EncoderFallback: {System.Text.InternalEncoderBestFitFallback}
encoderFallback: {System.Text.InternalEncoderBestFitFallback}
EncodingName: "Central European (Windows)"
HeaderName: "windows-1250"
IsBrowserDisplay: true
IsBrowserSave: true
IsMailNewsDisplay: true
IsMailNewsSave: true
IsReadOnly: true
IsSingleByte: true
m_codePage: 1250
m_deserializedFromEverett: false
m_isReadOnly: true
WebName: "windows-1250"
WindowsCodePage: 1250
Supponendo che tu stia usando una tastiera inglese, cosa succede se inserisci ±, § o € come parte della stringa (tutti si trovano su una tastiera del Regno Unito)? Se anche questi falliscono, il problema è sicuramente con la codifica 7 vs 8 bit, poiché tutti questi caratteri hanno codici superiori a 128 (cioè usano 8 bit) e quindi non possono essere elaborati correttamente con la codifica predefinita, che, molto probabilmente , è Latin1 o qualche sua variazione. C'è un modo per cambiare la codifica in UTF8? –
Sembra un problema con il carattere della sterlina codificato come carattere ASCII "esteso", che può essere interpretato solo se si conosce la tabella codici utilizzata (ovviamente un hash della password non include la tabella codici utilizzata per renderlo), quindi il metodo di codifica potrebbe giustamente rifiutare i caratteri ambigui codificati. UTF8 suona come la soluzione giusta. – David
Ciao ragazzi, grazie per i vostri commenti. @Aleks - Ho aggiunto questi tre caratteri: "± § €" alla mia stringa di test e tutti superano il test. A proposito, la mia tastiera è inglese (Irlanda) – lukk