4

有没有人能够在 Windows Phone Series 7 模拟器上使用 WCF 进行通信?

过去两天我一直在尝试,这对我来说正在发生。我可以让普通的 Silverlight 控件在 Silverlight 3 和 Silverlight 4 中工作,但不能在手机版本中工作。这是我尝试过的两个版本:

版本 1 - 使用异步模式

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

这个版本打破了这一行:

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

投掷System.NotSupportedException。异常不是很具有描述性,调用堆栈同样不是很有帮助:


   在 System.ServiceModel.DiagnosticUtility.ExceptionUtility.BuildMessage(异常 x)
   在 System.ServiceModel.DiagnosticUtility.ExceptionUtility.LogException(异常 x)
   在 System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(异常 e)
   在 System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress 地址)
   在 WindowsPhoneApplication2.MainPage.DoLogin()
   ……

版本 2 - 阻止 WCF 调用

这是不使用异步模式的版本。

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

System.ServiceModel.ClientBase<TChannel>此版本在构造函数中崩溃。调用堆栈有点不同:


   在 System.Reflection.MethodInfo.get_ReturnParameter()
   在 System.ServiceModel.Description.ServiceReflector.HasNoDisposableParameters(MethodInfo methodInfo)
   在 System.ServiceModel.Description.TypeLoader.CreateOperationDescription(ContractDescription contractDescription,MethodInfo methodInfo,MessageDirection 方向,ContractReflectionInfo reflectInfo,ContractDescription declaringContract)
   在 System.ServiceModel.Description.TypeLoader.CreateOperationDescriptions(ContractDescription contractDescription,ContractReflectionInfo 反射信息,类型 contractToGetMethodsFrom,ContractDescription declaringContract,MessageDirection 方向)
   在 System.ServiceModel.Description.TypeLoader.CreateContractDescription(ServiceContractAttribute contractAttr,类型 contractType,类型 serviceType,ContractReflectionInfo&reflectionInfo,对象 serviceImplementation)
   在 System.ServiceModel.Description.TypeLoader.LoadContractDescriptionHelper(类型 contractType,类型 serviceType,对象 serviceImplementation)
   在 System.ServiceModel.Description.TypeLoader.LoadContractDescription(类型 contractType)
   在 System.ServiceModel.ChannelFactory 1..ctor(绑定绑定,EndpointAddress 远程地址)1.CreateDescription()
   at System.ServiceModel.ChannelFactory.InitializeEndpoint(Binding binding, EndpointAddress address)
   at System.ServiceModel.ChannelFactory
   在 System.ServiceModel.ClientBase 1..ctor(字符串名称,布尔流)1..ctor(Binding binding, EndpointAddress remoteAddress)
   at Wcf.WcfClientBase
   在 Wcf.WcfClientBase`1..ctor(字符串名称)
   在 Wcf.AuthenticationClient..ctor()
   在 WindowsPhoneApplication2.MainPage.DoLogin()
   ...

有任何想法吗?

4

4 回答 4

7

正如 scottmarlowe 指出的那样,自动生成的服务引用是有效的。我的任务是弄清楚为什么该死的地狱它可以工作,而手动版本却不能。

我找到了罪魁祸首ChannelFactory。出于某种原因new ChannelFactory<T>().CreateChannel(),只是抛出了一个异常。我找到的唯一解决方案是提供您自己的通道实现。这涉及:

  1. 覆盖 ClientBase。(选修的)。
  2. 覆盖 ClientBase.CreateChannel。(选修的)。
  3. 使用 WCF 接口的特定实现子类 ChannelBase

现在,ClientBase 已经通过ChannelFactory属性提供了通道工厂的实例。如果你简单地CreateChannel取消它,你会得到同样的例外。您需要从内部实例化您在步骤 3 中定义的通道CreateChannel

这是所有看起来如何组合在一起的基本线框。

[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;如果您想在 WP7 上使用自己的 WCF 代码,您需要创建自己的频道类,而不是依赖ChannelFactory.

于 2010-03-20T11:03:29.607 回答
1

Windows Phone 不支持使用 ChannelFactory.CreateChannel() 创建动态代理。这记录在这里 - http://msdn.microsoft.com/en-us/library/ff426930(VS.96).aspx

在异步模式中使用“添加服务引用”机制使用服务将是正确的做法。

于 2010-03-23T15:29:13.367 回答
1

我就这个主题发表了一篇博文:http: //blogs.msdn.com/b/andypennell/archive/2010/09/20/using-wcf-on-windows-phone-7-walk-through.aspx

于 2010-09-20T23:00:55.420 回答
0

我没有遇到任何问题,但我通过“VS2010 Express for Windows Phone”b/c 执行的“添加服务参考...”路线,VS2010 RC 尚不支持 WP7 开发的该功能。Express 版本附带 WP7 开发人员的安装。

于 2010-03-19T12:02:15.587 回答