Question

Quelqu'un at-il été en mesure de communiquer en utilisant WCF sur l'émulateur Windows Phone 7 Series?

Je l'ai essayé pendant les deux derniers jours et ça se passe juste pour moi. Je peux obtenir un contrôle Silverlight normal de travailler dans les deux Silverlight 3 et Silverlight 4, mais pas la version de téléphone. Voici deux versions que j'ai essayé:

Version 1 - Utiliser Motif Async

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);

Cette version pauses sur cette ligne:

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

Lancer System.NotSupportedException. L'exception n'est pas très descriptif et callstack est également pas très utile:


   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 - Blocage appel WCF

Voici la version qui n'utilise pas le modèle async.

[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");

Cette plante version dans le constructeur de System.ServiceModel.ClientBase<TChannel>. La pile d'appel est un peu différente:


   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()
   ...

Toutes les idées?

Était-ce utile?

La solution

Comme scottmarlowe a souligné, le refrence service fonctionne généré automatiquement disponibles. J'ai mis sur la mission de travailler juste pourquoi Bordel cela fonctionne et la version manuelle ne fonctionne pas.

J'ai trouvé le coupable et il est ChannelFactory. Pour certains new ChannelFactory<T>().CreateChannel() raison jette juste une exception. La seule solution que je trouve est de fournir votre propre implémentation du canal. Cela implique:

  1. Remplacer ClientBase. (En option).
  2. Remplacer ClientBase.CreateChannel. (En option).
  3. ChannelBase de sous-classe avec une implémentation spécifique de votre interface WCF

Maintenant, ClientBase fournit déjà une instance de l'usine de canal à travers la propriété ChannelFactory. Si vous appelez simplement CreateChannel ce que vous obtiendrez la même exception. Vous devez instancier un canal que vous définissez à l'étape 3 de l'intérieur CreateChannel.

Ceci est le wireframe de base de la façon dont tout semble mis en place.

[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;. Si vous souhaitez utiliser votre propre code WCF sur WP7, vous devez créer votre propre classe de canal et ne pas compter sur ChannelFactory

Autres conseils

Création de proxy dynamique à l'aide ChannelFactory.CreateChannel () est pas pris en charge sur Windows Phone. Ceci est documenté ici - http://msdn.microsoft. com / fr-fr / bibliothèque / ff426930 (VS.96) .aspx

La consommation d'un service à l'aide du mécanisme « Ajouter une référence de service » dans un modèle de async serait la bonne façon de le faire.

Je n'ai pas eu de problèmes, mais je suis allé le « service de référence ajouter ... » route que je devais faire via « VS2010 Express pour Windows Phone » b / c VS2010 RC ne supporte pas encore cette fonctionnalité pour le développement WP7. La version Express est livré avec l'installation de la WP7 Developer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top