Silverlight & .Net Service Bus

Как только посещают мысли использовать указанную связку возникает вопрос: “Как сделать кроссдоменный запрос к сервису?”. Потому как интернет адрес к сервису находится в домене Microsoft и положить туда свой файл конфигурации никакой возможности нет. Хотя, если подумать, то мы не имеем физической возможности, но имеем возможность сделать это с помощью своего же сервиса.

Давайте попробуем связать наш сервис и Silverlight приложение через .Net Service Bus. В результате получим Silverlight приложение, которое будет отправлять данные на наш сервис и получать файл.

Прежде чем продолжить, рекомендую почитать о .Net Service Bus и необходимо установить Microsoft .NET Services SDK (July 2009 CTP).

Начнем с разработки сервиса. Для начала создадим консольное приложение и в список ссылок на сборки добавить еще одну ссылку на Microsoft.ServiceBus.dll (на моей машине она находится C:\Program Files (x86)\Microsoft .NET Services SDK (July 2009 CTP)\Assemblies\Microsoft.ServiceBus.dll). Добавим к сервису необходимый контракт, в нашем случае он выглядит так:

[ServiceContract(Name = "IEchoContract", 
Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IEchoContract
    {
        [OperationContract]
        string Echo(string text);

        [OperationContract]
        byte[] GetPicture();
    }

И еще один контракт, который позволит делать кроссдоменные запросы к сервису из Silverlight приложений:

[ServiceContract]
    public interface IPolicyRetriever
    {
        [OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
        Stream GetSilverlightPolicy();
    }

На следующем шаге зададим поведение для нашего сервиса:

[ServiceBehavior(Name = "EchoService", 
IncludeExceptionDetailInFaults = true, 
Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    class EchoService : IEchoContract, IPolicyRetriever
    {
        #region IEchoContract Members
        public string Echo(string text)
        {
            Console.WriteLine("Echoing: {0}", text);
            return text;
        }

        public byte[] GetPicture()
        {
            byte[] result = null;
            using (var file = File.Open("filePath.jpg", FileMode.Open, FileAccess.Read))
            {
                result = new byte[file.Length];
                file.Read(result, 0, result.Length);
            }
            return result;
        }
        #endregion

        #region IPolicyRetriever Members
        public Stream GetSilverlightPolicy()
        {
            string result = @"<?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>";
            return StringToStream(result);
        }
        #endregion

        private Stream StringToStream(string result)
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
            return new MemoryStream(Encoding.UTF8.GetBytes(result));
        }
    }

Теперь поехали в файл конфигурации нашего сервиса. В разделе <services> указываем описание нашего сервиса(<service>) и его конечных точек(endpoint):

   <services>
       <service name="ServiceBusService.Silverlight.EchoService" behaviorConfiguration="Metadata">
           <host>
               <baseAddresses>
                   <add baseAddress="http://azurelutay.servicebus.windows.net"/>
               </"/>
               </baseAddresses>
           </host>
           <endpoint contract="ServiceBusService.Silverlight.IEchoContract" address="EchoService"
                     binding="basicHttpRelayBinding" bindingConfiguration="default" />
           <endpoint address=""
                     binding="webHttpRelayBinding"
                     contract="ServiceBusService.Silverlight.IPolicyRetriever"
                     bindingConfiguration="default2"
                     behaviorConfiguration="webHttpBehaviour" />
       </service>
   </services>

Конечная точка c пустым атрибутом address выдает Silverlight приложению файл, необходимый для кроссдоменного достпука к сервису. Через другую точку происходит связь с логикой/поведением сервиса.

В разделе <bindings> указываем доступ к сервису без креденшелов для обеих типов связывания, которые мы используем:

<bindings>
   <basicHttpRelayBinding>
     <binding name="default">
       <security mode="None" relayClientAuthenticationType="None"/>
     </binding>
   </basicHttpRelayBinding>
   <webHttpRelayBinding>
     <binding name="default2">
       <security relayClientAuthenticationType="None"/>
     </binding>
   </webHttpRelayBinding>
</bindings>

Теперь у нас остался один раздел без конфигурации – это <behaviors>. В нем укажем локальный адрес для получения описания сервиса и настройки поведения для типа связывания webHttpBehaviour:

<behaviors>
    <serviceBehaviors>
        <behavior name="Metadata">
            <serviceMetadata httpGetEnabled="true" httpGetUrl="http://silverlight:1234/ServiceMeta" />
        </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
        <behavior name="webHttpBehaviour">
            <webHttp />
        </behavior>
    </endpointBehaviors>
</behaviors>

На этом конфигурацию сервиса можно считать законченой.

Дальше перейдем в метод точки входа в консольное приложение и реализуем механизм хостинга сервиса(описание поэтому смотри в доке по .Net Service Bus):

static void Main(string[] args)
{
    ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;

    string solutionName = "[Solution Name]";
    string solutionPassword = "[Solution Pwd]";

    Uri address = ServiceBusEnvironment.CreateServiceUri("http", solutionName, "EchoService");

    TransportClientEndpointBehavior userNamePasswordServiceBusCredential = newTransportClientEndpointBehavior();
    userNamePasswordServiceBusCredential.CredentialType = TransportClientCredentialType.UserNamePassword;
    userNamePasswordServiceBusCredential.Credentials.UserName.UserName = solutionName;
    userNamePasswordServiceBusCredential.Credentials.UserName.Password = solutionPassword;

    ServiceHost host = newServiceHost(typeof(EchoService));
   
    foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
    {
        endpoint.Behaviors.Add(userNamePasswordServiceBusCredential);
    }

    host.Open();

    Console.WriteLine("Service address: "+ address);
    Console.WriteLine("Press [Enter] to exit");
    Console.ReadLine();

    host.Close();
}

Что бы добавить прокси-класс в Silverlight приложение:

  1. Правый клик на Silverlight проекте;
  2. Из контекстного меню выбирает пункт “Add Service Seference”;
  3. В появившемся окне вводим адрес, указанный в файле конфигурации http://silverlight:1234/ServiceMeta, нажимаем кнопку “Go” и добавляем в проект
  4. Если у вас появилось окноimage , не пугайтесь, все по плану :)
  5. После проделаных операций открываем файл ServiceReferences.ClientConfig и удаляем вторую конечную точку, если она есть.

Дальше используем прокси-класс как обычно.

Пример Silverlight приложения, которое обращается к сервису на моем компьютере через .Net Service Bus ( необходим Silverlight 3 на клиенте, работает с сервисом когда включен комп.:) ):


Скачать решение
Опубліковані 22-07-2009 07:00 від Sergey Lutay
Зареєстрований як , , ,

Коментарі

Немає коментарів
Анонімні коментарі деактивовані. Увійдіть або Зареєструйтесь щоб мати доступ до ресурсів Спільноти.

Новини

Календар повідомлень

<March 2017>
SMTWTFS
2627281234
567891011
12131415161718
19202122232425
2627282930311
2345678

Пошук

Go

Категорії повідомлень

Синдикація

SkinName:iroha_Blog2