2011-08-18 15 views
12

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 
+1

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? –

+0

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

+0

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

risposta

2

ho sperimentato qualcosa di simile con asp, sono riuscito a aggirare il problema utilizzando la seguente configurazione

<system.web>  
<globalization 
fileEncoding="utf-8" 
requestEncoding="utf-8"  
responseEncoding="utf-8" 
culture="en-GB" 
uiCulture="en-GB"/> 
... 

A mia conoscenza il tag globalizzazione funziona lo stesso per WCF quando si imposta l'aggiornamento

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 

: appena controllato MSDN in fondo alla pagina si afferma quanto segue:

The ASP.NET configuration language allows you to specify the culture for individual services. The WCF does not support that configuration setting except in ASP.NET compatibility mode. To localize a WCF service that does not use ASP.NET compatibility mode, compile the service type into culture-specific assemblies, and have separate culture-specific endpoints for each culture-specific assembly.

Problemi correlati