【问题标题】:Silverlight 3 WCF Multiple ServersSilverlight 3 WCF 多服务器
【发布时间】:2011-07-26 09:17:54
【问题描述】:

请帮助...我快疯了...我有一个存在于几个不同服务器上的 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(字符串操作,对象 [] 输出,IAsyncResult 结果) 在 System.ServiceModel.ClientBase1.ChannelBase1.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 结果) 在 System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult 结果)}

【问题讨论】:

  • 在配置中更改端点地址时发生了什么?我相信这应该有效
  • @Richard - 查看我的编辑,谢谢。
  • 两个建议 - 请发布确切的错误消息,您可能想使用 Fiddler 查看失败的请求。
  • @rboarman - Fiddler 只返回 404 响应。例外情况相同,但我会根据您的要求发布,谢谢。
  • 请求是否发送到正确的服务器和端点?它是否使用正确的 IP 地址正确形成?仔细检查从 GetServiceAddress() 返回的地址是否在对服务器的请求中。另外,您在此之前是否看到任何失败的请求?也许对于 CrossDomain.xml 或 ClientAccessPolicy.xml?

标签: asp.net wcf silverlight-3.0


【解决方案1】:

我发现这些看起来很有希望:

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);
            });

【讨论】:

  • 我想就是这样......你给我的第一个链接有一个我开始使用的例子,它向我展示了我的方式的错误......我没有意识到我需要在我的地址末尾附加一个“/Services”。这是在我的服务中指定的,但我认为它是我的 .svc 文件的相关地址......它不是(为什么我没有想到它???)。我必须对此进行更多测试,但如果它在其他机器上运行,我会在明天奖励你赏金(看起来不会有问题)。谢谢!
  • 祝你好运,如果您需要更多帮助,欢迎来电
【解决方案2】:

(分辨率) 我能够通过观察@rboarman 答案的第一个链接中所做的事情来找到答案。该链接指向 Omar Al Zabir 撰写的博客。 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/

我认为服务配置中的“服务”地址是我的 .svc 文件的相对地址,但显然我错了。

【讨论】:

    猜你喜欢
    • 2010-12-22
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多