Frage

Hat jemand in der Lage gewesen, mit WCF auf Windows Phone Series 7-Emulator zu kommunizieren?

Ich habe für die letzten zwei Tage versucht, und es geschieht nur für mich. Ich kann ein normales Silverlight-Steuerelement zur Arbeit in beiden Silverlight 3 und Silverlight 4, bekomme aber nicht die Telefon Version. Hier sind zwei Versionen, dass ich versucht habe:

Version 1 - Mit Async Muster

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost/wcf/Authentication.svc");
Wcf.IAuthentication auth1 = new ChannelFactory<Wcf.IAuthentication>(basicHttpBinding, endpointAddress).CreateChannel(endpointAddress);

AsyncCallback callback = (result) =>
{

    Action<string> write = (str) =>
    {
        this.Dispatcher.BeginInvoke(delegate
        {
            //Display something
        });
    };

    try
    {
        Wcf.IAuthentication auth = result.AsyncState as Wcf.IAuthentication;
        Wcf.AuthenticationResponse response = auth.EndLogin(result);
        write(response.Success.ToString());
    }
    catch (Exception ex)
    {
        write(ex.Message);
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
};

auth1.BeginLogin("user0", "test0", callback, auth1);

Diese Version bricht auf dieser Linie:

Wcf.IAuthentication auth1 = new ChannelFactory<Wcf.IAuthentication>(basicHttpBinding, endpointAddress).CreateChannel(endpointAddress);

Throwing System.NotSupportedException. Die Ausnahme ist nicht sehr aussagekräftig und die Aufrufliste ist ebenfalls nicht sehr hilfreich:


   at System.ServiceModel.DiagnosticUtility.ExceptionUtility.BuildMessage(Exception x)
   at System.ServiceModel.DiagnosticUtility.ExceptionUtility.LogException(Exception x)
   at System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(Exception e)
   at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address)
   at WindowsPhoneApplication2.MainPage.DoLogin()
   ....

Version 2 - Blocking WCF Aufruf

Hier ist die Version, die nicht von dem Asynchron-Muster nicht verwendet.

[System.ServiceModel.ServiceContract]
public interface IAuthentication
{
    [System.ServiceModel.OperationContract]
    AuthenticationResponse Login(string user, string password);
}

public class WcfClientBase<TChannel> : System.ServiceModel.ClientBase<TChannel> where TChannel : class {
        public WcfClientBase(string name, bool streaming)
            : base(GetBinding(streaming), GetEndpoint(name)) {
            ClientCredentials.UserName.UserName = WcfConfig.UserName;
            ClientCredentials.UserName.Password = WcfConfig.Password;
        }
        public WcfClientBase(string name) : this(name, false) {}

        private static System.ServiceModel.Channels.Binding GetBinding(bool streaming) {
            System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding();
            binding.MaxReceivedMessageSize = 1073741824;
            if(streaming) {
                //binding.TransferMode = System.ServiceModel.TransferMode.Streamed;
            }
            /*if(XXXURLXXX.StartsWith("https")) {
                binding.Security.Mode = BasicHttpSecurityMode.Transport;
                binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            }*/
            return binding;
        }

        private static System.ServiceModel.EndpointAddress GetEndpoint(string name) {
            return new System.ServiceModel.EndpointAddress(WcfConfig.Endpoint + name + ".svc");
        }

        protected override TChannel CreateChannel()
        {
            throw new System.NotImplementedException();
        }
    }


auth.Login("test0", "password0");

Diese Version stürzt in System.ServiceModel.ClientBase<TChannel> Konstruktor. Der Call-Stack ist ein bisschen anders:


   at System.Reflection.MethodInfo.get_ReturnParameter()
   at System.ServiceModel.Description.ServiceReflector.HasNoDisposableParameters(MethodInfo methodInfo)
   at System.ServiceModel.Description.TypeLoader.CreateOperationDescription(ContractDescription contractDescription, MethodInfo methodInfo, MessageDirection direction, ContractReflectionInfo reflectionInfo, ContractDescription declaringContract)
   at System.ServiceModel.Description.TypeLoader.CreateOperationDescriptions(ContractDescription contractDescription, ContractReflectionInfo reflectionInfo, Type contractToGetMethodsFrom, ContractDescription declaringContract, MessageDirection direction)
   at System.ServiceModel.Description.TypeLoader.CreateContractDescription(ServiceContractAttribute contractAttr, Type contractType, Type serviceType, ContractReflectionInfo& reflectionInfo, Object serviceImplementation)
   at System.ServiceModel.Description.TypeLoader.LoadContractDescriptionHelper(Type contractType, Type serviceType, Object serviceImplementation)
   at System.ServiceModel.Description.TypeLoader.LoadContractDescription(Type contractType)
   at System.ServiceModel.ChannelFactory1.CreateDescription()
   at System.ServiceModel.ChannelFactory.InitializeEndpoint(Binding binding, EndpointAddress address)
   at System.ServiceModel.ChannelFactory1..ctor(Binding binding, EndpointAddress remoteAddress)
   at System.ServiceModel.ClientBase1..ctor(Binding binding, EndpointAddress remoteAddress)
   at Wcf.WcfClientBase1..ctor(String name, Boolean streaming)
   at Wcf.WcfClientBase`1..ctor(String name)
   at Wcf.AuthenticationClient..ctor()
   at WindowsPhoneApplication2.MainPage.DoLogin()
   ...

Irgendwelche Ideen?

War es hilfreich?

Lösung

Wie scottmarlowe wies darauf hin, das automagicly erzeugte Service refrence funktioniert einfach. Ich habe auf der Mission gesetzt, nur um herauszufinden, warum zum Teufel es funktioniert und die manuelle Version nicht.

Ich fand den Täter, und es ist ChannelFactory. Aus irgendeinem Grund new ChannelFactory<T>().CreateChannel() wirft nur eine Ausnahme. Die einzige Lösung, die ich gefunden ist eine eigene Implementierung des Kanals zur Verfügung zu stellen. Dies beinhaltet:

  1. außer Kraft setzen Client. (Optional).
  2. außer Kraft setzen ClientBase.CreateChannel. (Optional).
  3. Subclass ChannelBase mit einer spezifischen Implementierung Ihrer WCF-Schnittstelle

Nun Client bietet bereits eine Instanz des Kanalfactory durch ChannelFactory Eigenschaft. Wenn Sie einfach CreateChannel abzublasen, dass würden Sie die gleiche Ausnahme erhalten. Sie benötigen einen Kanal instanziieren, dass Sie in Schritt 3 aus CreateChannel definieren.

Dies ist das grundlegende Drahtgitter, wie es sieht alles zusammen.

[DataContractAttribute]
public partial class AuthenticationResponse {
[DataMemberAttribute]
public bool Success {
    get; set;
}

[System.ServiceModel.ServiceContract]
public interface IAuthentication
{
    [System.ServiceModel.OperationContract(AsyncPattern = true)]
    IAsyncResult BeginLogin(string user, string password, AsyncCallback callback, object state);
    AuthenticationResponse EndLogin(IAsyncResult result);
}

public class AuthenticationClient : ClientBase<IAuthentication>, IAuthentication {

    public AuthenticationClient(System.ServiceModel.Channels.Binding b, EndpointAddress ea):base(b,ea)
    {
    }

    public IAsyncResult BeginLogin(string user, string password, AsyncCallback callback, object asyncState)
    {
        return base.Channel.BeginLogin(user, password, callback, asyncState);
    }

    public AuthenticationResponse EndLogin(IAsyncResult result)
    {
        return Channel.EndLogin(result: result);
    }

    protected override IAuthentication CreateChannel()
    {
        return new AuthenticationChannel(this);
    }

    private class AuthenticationChannel : ChannelBase<IAuthentication>, IAuthentication
    {
        public AuthenticationChannel(System.ServiceModel.ClientBase<IAuthentication> client)
        : base(client)
        {
        }

        public System.IAsyncResult BeginLogin(string user, string password, System.AsyncCallback callback, object asyncState)
        {
            object[] _args = new object[2];
            _args[0] = user;
            _args[1] = password;
            System.IAsyncResult _result = base.BeginInvoke("Login", _args, callback, asyncState);
            return _result;
        }

        public AuthenticationResponse EndLogin(System.IAsyncResult result)
        {
            object[] _args = new object[0];
            AuthenticationResponse _result = ((AuthenticationResponse)(base.EndInvoke("Login", _args, result)));
            return _result;
        }
    }
}

TLDR;. Wenn Sie Ihren eigenen WCF-Code auf WP7 verwenden, müssen Sie Ihre eigene Kanal-Klasse erstellen und mich nicht auf ChannelFactory

Andere Tipps

Dynamische Proxy-Erstellung mit ChannelFactory.CreateChannel () nicht auf Windows Phone unterstützt. Dies wird hier dokumentiert - http://msdn.microsoft. com / en-us / library / ff426930 (VS.96) aspx

einen Dienst Konsumieren mit dem ‚Dienstverweis hinzufügen‘ Mechanismus in einem Asynchron-Mustern wäre die richtige Art und Weise zu tun.

Ich habe keine Probleme gehabt, aber ich ging den „Dienstverweis hinzufügen ...“ Route, die ich hatte über „VS2010 Express für Windows Phone“ zu tun b / c VS2010 RC noch nicht diese Funktion unterstützen für WP7 Entwicklung. Die Express-Version kommt mit der Installation von WP7 Entwickler.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top