WCF Silverlight CommunicationException - PullRequest
       25

WCF Silverlight CommunicationException

1 голос
/ 12 августа 2011

Этот пост будет длинным, и я заранее извиняюсь за это.

Я пытаюсь заставить приложение Silverlight взаимодействовать со службой, которую я запускаю из visual studio, сейчас она не размещена в IIS.Я стараюсь иметь как можно меньше кода и конфигурации для этого прототипа, как минимум.В Интернете полно вопросов и ответов, но ни один из них, похоже, не подходит для моего конкретного затруднения.

Мое сервисное решение имеет SimpleServiceAsyncResult, который реализует интерфейс IAsyncResult, интерфейс сервиса, ISimpleService ифактическая реализация сервиса в SimpleService.Этот сервис реализован следующим образом:

public class SimpleService : ISimpleService
{
    public IAsyncResult BeginSimpleMethod(string msg, AsyncCallback callback, object state)
    {
        return new SimpleServiceAsyncResult<string>(msg);
    }

    public string EndSimpleMethod(IAsyncResult result)
    {
        SimpleServiceAsyncResult<string> res = result as SimpleServiceAsyncResult<string>;
        return res.Result;
    }

    public string SimpleMethod(string msg)
    {
        return msg;
    }


    public Message ProvideCrossDomainFile()
    {
        FileStream fileStream = File.Open(@"CrossDomain.xml", FileMode.Open, FileAccess.Read, FileShare.Read);

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.DtdProcessing = DtdProcessing.Parse;

        XmlReader reader = XmlReader.Create(fileStream, settings);

        Message result =  Message.CreateMessage(MessageVersion.None, "", reader);
        return result;
    }

    public Message ProvidePolicyFile()
    {
        FileStream fileStream = File.Open(@"ClientAccessPolicy.xml", FileMode.Open, FileAccess.Read, FileShare.Read);
        XmlReader reader = XmlReader.Create(fileStream);
        Message result = Message.CreateMessage(MessageVersion.None, "", reader);
        return result;
    }
}

В проекте 2 файла xml;ClientAccessPolicy.xml и CrossDomain.xml, которые выглядят следующим образом:

ClientAccessPolicy.xml

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

CrossDomain.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="*" />
  <allow-http-request-headers-from domain="*" headers="SOAPAction" />
</cross-domain-policy> 

Наряду с этим это App.configЭто выглядит так:

App.config

<behaviors>
  <serviceBehaviors>
    <behavior name="SimpleServiceBehavior">
      <serviceMetadata httpGetEnabled="True"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

Теперь я хотел посмотреть, сработает ли все это добро.Поэтому я создал решение с консольным проектом, в котором есть только Program.cs и App.config.

Программа, конечно, ничего особенного, просто минимум:

       var factory = new ChannelFactory<ISimpleService>("SimpleService");
        ISimpleService service = factory.CreateChannel();

        var asResult = service.BeginSimpleMethod("tesmsg", null, null);

        Console.WriteLine("Data: " + service.EndSimpleMethod(asResult);

Этовсе работает хорошо, я получаю данные, которые я ищу обратно, поэтому я счастлив.Следующее, чего я хотел добиться, - это получить данные из той же службы с помощью приложения Silverlight.

Для этого я создал проект Silverlight в своем клиентском решении, создал ссылку на службу и выполнил некоторые операции.Я пытаюсь выполнить SimpleMethod, добавив некоторый код в свой файл MainPage.xaml.cs:

    void SimpleMethodCompletedProxyCallback(object sender, SimpleMethodCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            data = e.Result;
        }
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        SimpleServiceClient proxy = new SimpleServiceClient();

        proxy.SimpleMethodCompleted += new EventHandler<SimpleMethodCompletedEventArgs>(SimpleMethodCompletedProxyCallback);
        try
        {

            proxy.SimpleMethodAsync("teststring");
        }
        catch (CommunicationException cex)
        {
            label1.Content = cex.Message;
        }
    }

После завершения этой сантехники я подумал, что смогу получить некоторые данные, но он продолжает выдавать CommunicationExceptionиз сгенерированного кода ServiceReference, когда он пытается вызвать SimpleMethod:

        public string EndSimpleMethod(System.IAsyncResult result) {
            object[] _args = new object[0];
            string _result = ((string)(base.EndInvoke("SimpleMethod", _args, result)));
            return _result;
        }

Я просматривал эту тему в Интернете в течение нескольких часов, заканчивая CrossDomain.xml и ClientAccessPolicy.xml и методамиэто разоблачило бы это, но что бы я ни пытался, я продолжаю сталкиваться с одним и тем же исключением.Я абсолютно не знаю, что делать дальше, и я надеюсь, что вы можете помочь мне немного больше с этим.

С уважением

1 Ответ

2 голосов
/ 12 августа 2011

В вашем сервисном коде класс SimpleService реализует один интерфейс (ISimpleService), который, как я предполагаю, украшен [ServiceContract] и определяет пять контрактов операций (BeginSimpleMethod, EndSimpleMethod, SimpleMethod, ProvideCrossDomainFile, ProvidePolicyFile).Возможно, ProvidePolicyFile также снабжен [WebGet (UriTemplate = "/clientaccesspolicy.xml")].

Теперь, поскольку у вас есть только один интерфейс, у вас есть одна из двух вещей: конечная точка на сервереконечная точка SOAP (например, на основе basicHttpBinding), или конечная точка является конечной точкой REST (т. е. поведение webHttpBinding / webHttp).

Если это первое, то местоположение операциивозвращать clientaccesspolicy.xml не правильно.Согласно разделу замечаний в документации для WebGetAttribute , это пассивное поведение, которое будет учитываться, только если конечная точка имеет WebHttpBehavior.Silverlight будет искать этот файл политики в одном месте (http://your_service/clientaccesspolicy.xml), и он будет доступен где-то еще (http://your_service/endpoint, с заголовком SOAPAction, указывающим метод).

Если это последний, то Silverlight не можетпо умолчанию вызывать эти конечные точки (см. сообщения для вызова конечных точек REST / POX и REST / JSON из SL), поэтому они также не будут работать.

Сообщение вhttp://blogs.msdn.com/b/carlosfigueira/archive/2008/03/07/enabling-cross-domain-calls-for-silverlight-apps-on-self-hosted-web-services.aspx - это AFAIK «канонический» способ, позволяющий SL вызывать сервисы на собственных сервисах WCF. Вам понадобятся две конечные точки (вероятно, в двух интерфейсах), одна для сервиса как таковая, одна для политикифайл (ы). В сообщении более подробно об этой проблеме.

...