Laden...

WP7/WCF: EndInvoke() Fehler

Erstellt von Mazo vor 12 Jahren Letzter Beitrag vor 12 Jahren 3.077 Views
M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 12 Jahren
WP7/WCF: EndInvoke() Fehler

Hallo CSharper,

ich programmiere zur zeit an einer WindowsPhoneApp, die ein SOAP basierten Webservice nutzt. Den Service spreche ich über einen (aus dem WSDL-File) generierten WCF Client an. Alle Aufrufe erfolgen asyncrone. Leider habe ich Probleme beim Aufruf von EndInvoke (in der Reference.cs), wenn der Service ein Fehler zurück gibt. Theoretisch müsste der Client an der Stelle EndInvoke aufrufen und eine ClientException zurückgeben (ClientException ist in der WSDL beschrieben). Statt dessen kommt der folgende Fehler. Tritt keine fehler auf funktioneirt EndInvoke.

Fehlermeldung:
base.EndInvoke("getCubeState", _args, result) fails with
InvalidCastException bei System.ServiceModel.Dispatcher.XmlSerializerObjectSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
bei System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlReader reader, Boolean verifyObjectName)
bei System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName)
bei System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName)
bei System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader)
bei System.ServiceModel.Dispatcher.XmlSerializerFaultFormatter.CreateFaultException(MessageFault messageFault, String action)
bei System.ServiceModel.Dispatcher.FaultFormatter.Deserialize(MessageFault messageFault, String action)
bei System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
bei System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
bei System.ServiceModel.ClientBase1.ChannelBase1.EndInvoke(String methodName, Object[] args, IAsyncResult result)
bei WindowsPhoneStr.ServiceReferenceSoap.RemoteClient.RemoteClientChannel.EndgetCubeState(IAsyncResult result)
bei WindowsPhoneStr.ServiceReferenceSoap.RemoteClient.WindowsPhoneStr.ServiceReferenceSoap.IRemote.EndgetCubeState(IAsyncResult result)
bei WindowsPhoneStr.ServiceReferenceSoap.RemoteClient.OnEndgetCubeState(IAsyncResult result)
bei System.ServiceModel.ClientBase1.OnAsyncCallCompleted(IAsyncResult result)
bei System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
bei System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
bei System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.CallComplete(Boolean completedSynchronously, Exception exception)
bei System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.FinishSend(IAsyncResult result, Boolean completedSynchronously)
bei System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.SendCallback(IAsyncResult result)
bei System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
bei System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
bei System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.OnGetResponse(IAsyncResult result)
bei System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClassa.<InvokeGetResponseCallback>b__8(Object state2)
bei System.Threading.ThreadPool.WorkItem.doWork(Object o)
bei System.Threading.Timer.ring()

Das Problem beschränkt sich scheinbar auf WP7+WCF. Der gleiche Service funktioniert aus einer WPF anwendung einwandfrei.

Hier der Code, den ich verwende:



public IAsyncResult BegingetCubeState(AsyncCallback callback, object asyncState)
{
object[] _args = new object[0];
IAsyncResult _result = base.BeginInvoke("getCubeState", _args, callback, asyncState);
return _result;
}

public CubeState EndgetCubeState(IAsyncResult result)
{
object[] _args = new object[0];
CubeState _result = ((CubeState)(base.EndInvoke("getCubeState", _args, result)));
return _result;
}


[GeneratedCode("System.Xml", "4.0.30319.208";)]
[DebuggerStepThrough]
[XmlType(Namespace = "http://exception.cllink.de";)]
public class ClientException : object, INotifyPropertyChanged
{
private string errorCodeField;

private string exceptionMessageField;

private string exceptionTypeField;

/// <remarks/>
[XmlElement(IsNullable = true, Order = 0)]
public string errorCode
{
get { return errorCodeField; }
set
{
errorCodeField = value;
RaisePropertyChanged("errorCode";);
}
}

/// <remarks/>
[XmlElement(IsNullable = true, Order = 1)]
public string exceptionMessage
{
get { return exceptionMessageField; }
set
{
exceptionMessageField = value;
RaisePropertyChanged("exceptionMessage";);
}
}

/// <remarks/>
[XmlElement(IsNullable = true, Order = 2)]
public string exceptionType
{
get { return exceptionTypeField; }
set
{
exceptionTypeField = value;
RaisePropertyChanged("exceptionType";);
}
}

public event PropertyChangedEventHandler PropertyChanged;

protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler propertyChanged = PropertyChanged;
if ((propertyChanged != null))
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}


Habt ihr eine Idee, wo genau das Problem liegt und wie man es beheben kann?

Vielen Dank,
Mazo

N
22 Beiträge seit 2007
vor 12 Jahren

Hallo Mazo,
ich hatte bei mir ein aehnliches Problem.

Du haengst dich doch sicher an dem Event, das geraised wird, nachdem die Asynchrone Anfrage beendet wurde, oder?
("getCubeStateCompleted" muesste es sein.)

Beim Eventhandler musst du bei den EventArgs erst auf Error ueberpruefen!
Falls der Error != null ist, darfst du nicht auf das Result zugreifen. Sonst wird eine Exception geworfen.

(Zumindest war es bei mir das Problem. Ich weiss allerdings nicht mehr, welcher ExceptionType es bei mir war.)

Edit: Schau dann auch mal in dem generierten Code der Reference.cs:
Bei den Gettern der "Result" Property der ....MethodCompletedEventArgs gibt es jedes Mal einen Aufruf von "base.RaiseExceptionIfNecessary();"

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 12 Jahren

Hallo normen,

der Fehler tritt genau beim Aufruf von base.EndInvoke("getCubeState", _args, result))); auf. Einfach das EndInvoke nicht aufzurufen, verhindert natürlich den Fehler, allerdings bekomme ich dann trotzdem nicht die ClientException zurück. In dieser stehen allerdings die wichtigen Details, was genau schief gelaufen ist.

//edit
die completed Methode wird aufgerufen, allerdings fliegt der Fehelr schon vorher...


public getCubeStateCompletedEventArgs (object[] results, Exception exception, bool cancelled, object userState) : base(exception, cancelled, userState)
{
this.results = results;
}
public string Result
        {
            get
            {
                base.RaiseExceptionIfNecessary();
                return ((string)(results[0]));
            }
        }


dabei sind: results ein array mit einem objeckt vom typ null, exception null, cancelled false, userstate null

N
22 Beiträge seit 2007
vor 12 Jahren

Wie laueft der ServiceAufruf in deinem Wp-Client denn prinzipiell ab?
(Ohne autogenerated Code.)

Ich abonniere erst das completed-Event des Asynchronen Aufrufes und rufe dann die Asynchrone WCF-Methode auf.
Im Handler ueberpruefe ich dann, ob ein Fehler aufgetreten ist und danach greife ich auf das Result zu. In den Eventargs habe ich dann im error die Exception.


client.CancelCompleted += (sender, ea) => 
{
    If(ea.Error != null)
    //ErrorHandling
    else
    {
          //Valid Result handling
     }
}

client.CancelAsync(idToCancel);

..oder kann es vielleicht sein, dass du quasi die "FirstChanceException" im Debugger siehst, die gehandlet wird und nachher in der Error-Property steht.
(Allerdings bin ich mir nicht sicher, ob "intern" eine Exception geworfen wird, wenn etwas schief gegangen ist, oder nur die Error-Property gesetzt wird.)

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 12 Jahren

Also es läuft so ab (Bsp für Login und nicht getCubeState):


private Service()
{
_remoteClient = new RemoteClient("IRemotePort";); _remoteClient.loginCompleted += RemoteClientLoginCompleted;
}

public void Login(string username, string password)
{
_remoteClient.loginAsync(username, password);
}

private void RemoteClientLoginCompleted(object sender, loginCompletedEventArgs e)
{
//do sth.
}



public IAsyncResult Beginlogin(login request, AsyncCallback callback, object asyncState)
{
object[] _args = new object[1];
_args[0] = request;
IAsyncResult _result = base.BeginInvoke("login", _args, callback, asyncState);
return _result;
}

public loginResponse Endlogin(IAsyncResult result)
{
object[] _args = new object[0];
Debugger.Break();
try
{
loginResponse _result =
((loginResponse)
(base.EndInvoke("login", _args, result)));
return _result;
}
catch(Exception ex)
{
return new loginResponse();
}
}


Der Aufruf läuft so:
Login(...)
Beginlogin(...)
EndLogin(...), Hier ist result erst gefüllt, mit dem ((System.ServiceModel.Channels.ServiceChannel.SendAsyncResult)(result)).Rpc.Reply, wo der reply drins teht, dann kommt der Fehler bei base.EndInvoke, innerhalb des try blocks, dann geht er raus und der Reply ist aus result auch nicht mehr zu bekommen.
RemoteClientLoginCompleted(object sender, loginCompletedEventArgs e) wobei e.Error und e.Expression beide Could not evaluate expression haben.

N
22 Beiträge seit 2007
vor 12 Jahren

Ah, ok.
Ich glaube, dann bin ich mit meiner ersten Vermutung auf den Holzweg.

Fehlermeldung:
InvalidCastException bei System.ServiceModel.Dispatcher.XmlSerializerObjectSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)

Sieht danach aus, als ob er beim parsen der Xml-Nachricht ein Problem hat.
Wurde die Serviceschnittstelle vielleicht geaendert und du hast noch einen alten Stand?

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 12 Jahren

Ich hab gerade nochmal Update ServiceReference gemacht, leider ohne Erfolg 😦
Im Reply steht:


..??Í'..*Ü5...E..? û@.?..NÀ¨*eÀ¨m.ÞUNɁ{G?J.P.Äà9ª..HTTP/1.0 500 Internal Server Error..Server: Apache-Coyote/1.1..Content-Type: text/xml;charset=UTF-8..Content-Length: 583..Date: Mon, 30 May 2011 12:43:19 GMT..X-Cache: MISS from proxy.link.de..Via: 1.0 proxy.link.de:8080 (squid/2.6.STABLE19)..Proxy-Connection: close....
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Unknown user</faultstring>
<detail>
<ns1:ClientException xmlns:ns1="http://cllink.de/" xmlns:ns2="http://exception.cllink.de" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:ClientException">
<ns2:errorCode>MX1046</ns2:errorCode>
<ns2:exceptionMessage>Unknown user</ns2:exceptionMessage>
<ns2:exceptionType>SubjectNotAuthorized</ns2:exceptionType>
</ns1:ClientException>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>

Sieht eigentlich nach einem validen Code aus...

N
22 Beiträge seit 2007
vor 12 Jahren

Es koennte sein, dass es an der Servermeldung liegt:> Fehlermeldung:

HTTP/1.0 500 Internal Server Error

Dazu noch folgender Link:
Creating and Handling Faults in Silverlight

Ich bin mir aber ehrlich gesagt nicht sicher, ob es daran liegt.
Durch einen Kollegen weiss ich, dass es Probleme bei FaultExceptions und Silverlight geben kann.
Inwieweit das aber auf WP7 zutrifft, kann ich dir leider nicht sagen.

Selber benutze ich zur Kommunikation zwischen Server <-> WP7 einen selbst gehosteten Wcf-Service. Zur Exceptionbehandlung habe ich eigene FaultExceptions erstellt und damit funktioniert das Handling auf Clientseite einwandfrei.

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 12 Jahren

Die Lösung mit den eigenem WCF Servcie wird vermutlich die Finale werden,
ich werde heute mal die WP7.1 DevTools probieren, vlt ist das Problem damit behoben.

Viele Dank, für deine Hilfe 😉