문제

Windows Phone Series 7 에뮬레이터에서 WCF를 사용하여 통신 할 수있는 사람이 있습니까?

나는 지난 이틀 동안 노력해 왔고 그것은 단지 나를 위해 일어나고 있습니다. 나는 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. 예외는 그다지 설명이 아니며 Callstack은 그다지 도움이되지 않습니다.

system.servicemodel.diagnosticutility.xception ilfeance.servicemodel.diagnosticemodel.diagnosticutility.xceptionitility.logexception (예외 x)의 System.serviceModel.DiagnosticUtility.Exceptionitility.TiagnosticUtorror (예외) 1의 exceptoror (예외 x)의 System.servicemodel.diagnosticutility.exception. .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> 건설자. 통화 스택은 약간 다릅니다.

at System.Reflection.methodinfo.get_returnparameter ()에서 system.servicemodel.description.servicereflector.hasnodisposableparameters (methodinfo methodinfo)에서 system.servicemodel.description.typeloader.typeloader.cepleationporation (contracteportion) 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 system.servicemodel.description.typeloader.loadContractDescriptionHelper의 ServiceMementation) mentation) system.servicemodel.description.typeloader.loadContractDescription (system.servicemodel.channelfactory의 계약 유형)1.CreateDescription()
   at System.ServiceModel.ChannelFactory.InitializeEndpoint(Binding binding, EndpointAddress address)
   at System.ServiceModel.ChannelFactory1..ctor (System.servicemodel.clientbase의 결합 결합, EndpointAddress Remoteaddress)1..ctor(Binding binding, EndpointAddress remoteAddress)
   at Wcf.WcfClientBase1..ctor (문자열 이름, 부울 스트리밍) wcf.wcfclientbase`1..ctor (문자열 이름) wcf.authenticationclient..ctor ()의 windowsphoneapplication2.mainpage.dologin () ...

어떤 아이디어?

도움이 되었습니까?

해결책

Scottmarlowe가 지적했듯이 자동 생성 된 서비스 굴절은 작동합니다. 나는 그것이 작동하는 이유와 수동 버전이 그렇지 않은 이유를 해결하기 위해 미션을 시작했습니다.

나는 범인을 찾았다 ChannelFactory. 몇 가지 이유 new ChannelFactory<T>().CreateChannel() 예외를 던졌습니다. 내가 찾은 유일한 해결책은 채널의 자신의 구현을 제공하는 것입니다. 여기에는 다음이 포함됩니다.

  1. 클라이언트베이스를 무시합니다. (선택 과목).
  2. ClientBase.CreateChannel을 재정의합니다. (선택 과목).
  3. WCF 인터페이스의 특정 구현을 갖춘 서브 클래스 채널베이스

이제 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.

다른 팁

channelfactory.createchannel ()을 사용한 동적 프록시 생성은 Windows Phone에서 지원되지 않습니다. 여기에 문서화되어 있습니다. http://msdn.microsoft.com/en-us/library/ff426930(vs.96).aspx

비동기 패턴으로 '서비스 참조 추가'메커니즘을 사용하여 서비스를 소비하는 것이 올바른 방법입니다.

아무런 문제가 없었지만 Windows Phone 용 VS2010 Express를 통해해야 할 "서비스 참조 ..."경로를 사용했습니다. RC는 아직 WP7 개발 기능을 지원하지 않습니다. Express 버전은 WP7 개발자의 설치와 함께 제공됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top