加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

在Windows Phone 7上使用WCF的System.UnsupportedException

发布时间:2020-12-14 02:07:06 所属栏目:Windows 来源:网络整理
导读:有没有人能够在 Windows Phone Series 7模拟器上使用WCF进行通信? 在过去的两天里我一直在努力,而这正好适合我.我可以在Silverlight 3和Silverlight 4中使用普通的Silverlight控件,但不能使用手机版本.这是我尝试过的两个版本: 版本1 – 使用异步模式 Basi
有没有人能够在 Windows Phone Series 7模拟器上使用WCF进行通信?

在过去的两天里我一直在努力,而这正好适合我.我可以在Silverlight 3和Silverlight 4中使用普通的Silverlight控件,但不能使用手机版本.这是我尝试过的两个版本:

版本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.例外情况不是很具描述性,而且callstack同样不是很有用:


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

版本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>中崩溃.构造函数.调用堆栈有点不同:


   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,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,Object serviceImplementation)
   at System.ServiceModel.Description.TypeLoader.LoadContractDescription(Type contractType)
   at System.ServiceModel.ChannelFactory1..ctor(Binding binding,EndpointAddress remoteAddress)
   at System.ServiceModel.ClientBase1..ctor(String name,Boolean streaming)
   at Wcf.WcfClientBase`1..ctor(String name)
   at Wcf.AuthenticationClient..ctor()
   at WindowsPhoneApplication2.MainPage.DoLogin()
   ...
1.CreateDescription() at System.ServiceModel.ChannelFactory.InitializeEndpoint(Binding binding,EndpointAddress address) at System.ServiceModel.ChannelFactory1..ctor(Binding binding,EndpointAddress remoteAddress) at Wcf.WcfClientBase

有任何想法吗?

解决方法

正如scottmarlowe指出的那样,自动生成的服务引用才起作用.我已经开始着手解决为什么它的血腥地狱和手动版本没有.

我找到了罪魁祸首,它是ChannelFactory.出于某种原因,新的ChannelFactory< T>().CreateChannel()只会引发异常.我找到的唯一解决方案是提供您自己的频道实现.这包括:

>覆盖ClientBase. (可选的).
>覆盖ClientBase.CreateChannel. (可选的).
> Subclass ChannelBase,具有WCF接口的特定实现

现在,ClientBase已经通过ChannelFactory属性提供了通道工厂的实例.如果您只是调用CreateChannel,则会得到相同的异常.您需要在CreateChannel中实例化您在步骤3中定义的通道.

这是它们如何组合在一起的基本线框.

[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,object asyncState)
    {
        return base.Channel.BeginLogin(user,password,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,System.AsyncCallback callback,object asyncState)
        {
            object[] _args = new object[2];
            _args[0] = user;
            _args[1] = password;
            System.IAsyncResult _result = base.BeginInvoke("Login",_args,asyncState);
            return _result;
        }

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

TLDR;如果您想在WP7上使用自己的WCF代码,则需要创建自己的通道类,而不是依赖ChannelFactory.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读