Несколько серверов Silverlight 3 WCF - PullRequest
1 голос
/ 31 марта 2011

Пожалуйста, помогите ... Я схожу с ума .... У меня есть служба wcf, которая существует на нескольких разных серверах. Мне нужно динамически изменить адрес конечной точки на моем клиенте Silverlight в зависимости от среды, в которой он находится. В настоящее время я получаю очень подробную ошибку 404 (сарказм), когда пытаюсь изменить адрес с помощью кода или путем ручного обновления файла конфигурации клиента.

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

У меня есть следующий сервис.

<system.serviceModel>
 <bindings>
  <basicHttpBinding>
    <binding name="DrawingServiceBasicHttp">
      <readerQuotas maxStringContentLength="2147483647" />
    </binding>
  </basicHttpBinding>
</bindings>

<service behaviorConfiguration="md" name="My.DrawingService">
    <endpoint address="Services" 
              binding="basicHttpBinding" 
              bindingConfiguration="DrawingServiceBasicHttp"
              name="DrawingServiceEndPoint" 
              contract="MyServices.IDrawingService" />
    <endpoint address="mex" 
              binding="mexHttpBinding" 
              bindingConfiguration=""
              name="DrawingMex" 
              contract="IMetadataExchange" />
 <behaviors>
  <serviceBehaviors>
    <behavior name="md">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

Мой клиентский конфиг

<bindings>
        <basicHttpBinding>
            <binding name="DrawingServiceEndPoint" maxBufferSize="2147483647"
                maxReceivedMessageSize="2147483647">
                <security>
                    <transport>
                        <extendedProtectionPolicy policyEnforcement="Never" />
                    </transport>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://MyHostName/Services/DrawingService.svc/Services"
            binding="basicHttpBinding" bindingConfiguration="DrawingServiceEndPoint"
            contract="EvalDrawingService.IDrawingService" name="DrawingServiceEndPoint" />
    </client>

В коде пытается установить адрес:

EvalDrawingService.DrawingServiceClient client = new EvalDrawingService.DrawingServiceClient("DrawingServiceEndPoint", GetServiceAddress());

Я подтвердил, что адрес, который выдается с помощью GetServiceAddress(), существует и что я могу использовать браузер, чтобы убедиться, что он существует (не говоря уже о том, что я могу подключиться к нему с помощью wcftestclient).

Исключение:

{System.ServiceModel.CommunicationException: удаленный сервер возвратил ошибку: NotFound. ---> System.Net.WebException: удаленный сервер возвратил ошибку: NotFound. ---> System.Net.WebException: удаленный сервер возвратил ошибку: NotFound. в System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse (IAsyncResult asyncResult) в System.Net.Browser.BrowserHttpWebRequest. <> c_ DisplayClass5.b _4 (объект sendState) в System.Net.Browser.AsyncHelper. <> c_ DisplayClass4.b _1 (объект sendState) --- Конец внутренней трассировки стека исключений --- в System.Net.Browser.AsyncHelper.BeginOnUI (SendOrPostCallback beginMethod, состояние объекта) в System.Net.Browser.BrowserHttpWebRequest.EndGetResponse (IAsyncResult asyncResult) в System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse (результат IAsyncResult) --- Конец внутренней трассировки стека исключений --- в System.ServiceModel.AsyncResult.End [TAsyncResult] (результат IAsyncResult) в System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End (результат SendAsyncResult) в System.ServiceModel.Channels.ServiceChannel.EndCall (действие String, выходы Object [], результат IAsyncResult) at System.ServiceModel.ClientBase 1.ChannelBase 1.EndInvoke (String methodName, Object [] args, результат IAsyncResult) в EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.DrawingServiceClientChannel.EndGetEvalAreaDrawing (результат IAsyncResult) в EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.EvaluaionAncillaryControl.EvalDrawingService.IDrawingService.EndGetEvalAreaDrawing (результат IAsyncResult) в EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.OnEndGetEvalAreaDrawing (результат IAsyncResult) at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted (результат IAsyncResult)}

Ответы [ 2 ]

1 голос
/ 12 апреля 2011

(РАЗРЕШЕНИЕ) Я смог найти ответ, наблюдая за тем, что делается в первой ссылке в ответе @rboarman.Ссылка на блог автора Омара Аль Забира.http://omaralzabir.com/dynamically-set-wcf-endpoint-in-silverlight/

Я использовал следующий метод:

public class DynamicEndpointHelper
{
// Put the development server site URL including the trailing slash
// This should be same as what's set in the Dropthings web project's 
// properties as the URL of the site in development server
private const string BaseUrl = "http://localhost:8000/Dropthings/";

public static string ResolveEndpointUrl(string endpointUrl, string xapPath)
{
    string baseUrl = xapPath.Substring(0, xapPath.IndexOf("ClientBin"));
    string relativeEndpointUrl = endpointUrl.Substring(BaseUrl.Length);
    string dynamicEndpointUrl = baseUrl + relativeEndpointUrl;
    return dynamicEndpointUrl;
}
}

и назвал его так:

DynamicEndpointHelper.ResolveEndpointUrl(service.Endpoint.Address.Uri.ToString(), 
    App.Current.Host.Source.ToString()));

Это позволило мне понять, что правильный путьдля вызова используйте адрес как:

http://MyServer/Services/MyService.svc/Services //This is what I specified it in the web.config

вместо просто

http://MyServer/Services/MyService.svc/

Я думал, что адрес "Services" в конфигурации службы был относительным адресом для моего .svcфайл, но, очевидно, я был не прав.

0 голосов
/ 12 апреля 2011

Я нашел их многообещающими:

http://omaralzabir.com/dynamically-set-wcf-endpoint-in-silverlight/

http://blogs.artinsoft.net/mrojas/archive/2011/03/23/dynamically-change-wcf-endpoint.aspx

Кроме того, вот некоторый код из моего серверного проекта, в котором я могу изменить конечную точкуна лету, используя каналы.Я не пробовал это от Silverlight.он работает со стороны сервера.

    /// <summary>
    /// This class contains utility methods related to invoking WCF services.
    /// http://msdn.microsoft.com/en-us/library/ms734681.aspx
    /// </summary>
    public static class ServiceInvoker
    {
        /// <summary>
        /// Alternative to the using statement to handle exceptions thrown by the Close method
        /// by calling the Abort method to ensure the transition to the Closed state.
        /// </summary>
        /// <param name="action">
        /// The action.
        /// </param>
        /// <typeparam name="TService">
        /// The service type.
        /// </typeparam>
        public static void UsingProxy<TService>(Action<TService> action)
            where TService : class, ICommunicationObject, IDisposable, new()
        {
            // create an instance of TService and invoke the action
            TService service = new TService();
            service.InvokeAction(action);
        }
        /// <summary>
        /// Alternative to the using statement to handle exceptions thrown by the Close method
        /// by calling the Abort method to ensure the transition to the Closed state.
        /// </summary>
        /// <param name="action">
        /// The action.
        /// </param>
        /// <typeparam name="TService">
        /// The service type.
        /// </typeparam>
        public static void UsingChannel<TService>(ChannelFactory<TService> channelFactory, Action<TService> action)
            where TService : class
        {
            // create an instance of TService and invoke the action
            TService service = channelFactory.CreateChannel();
            service.InvokeAction(action);
        }
        /// <summary>
        /// Alternative to the using statement to handle exceptions thrown by the Close method
        /// by calling the Abort method to ensure the transition to the Closed state.
        /// </summary>
        /// <param name="action">
        /// The action.
        /// </param>
        /// <typeparam name="TService">
        /// The service type.
        /// </typeparam>
        public static void UsingFactory<TService>(Action<TService> action)
            where TService : class
        {
            // TODO: cache the channel factory of TService
            ChannelFactory<TService> factory = new ChannelFactory<TService>("*");
            // create an instance of TService and invoke the action
            TService service = factory.CreateChannel();
            service.InvokeAction(action);
        }
        /// <summary>
        /// Invokes an action on a service then disposes the service channel.
        /// </summary>
        /// <typeparam name="TService">
        /// The service type.
        /// </typeparam>
        /// <param name="service">
        /// The service.
        /// </param>
        /// <param name="action">
        /// The action.
        /// </param>
        private static void InvokeAction<TService>(this TService service, Action<TService> action)
            where TService : class
        {
            try
            {
                // invoke action with service as its parameter
                action(service);
            }
            catch (Exception)
            {
                // todo: add logging here
                throw;
            }
            finally
            {
                // always close or abort the service channel
                ((ICommunicationObject)service).CloseOrAbort();
            }
        }
    }

Вот как я его использую:

ServiceInvoker.UsingChannel<IMyProxy>(new ChannelFactory<IMyProxy>(new NetTcpBinding(), myServer.EndPointReference.Address), server =>
            {
                result = server.CallAMethod(passSomeData);
            });
...