2011-03-30 134 views
1

请帮助...我要疯了....我有一个wcf服务存在于几个不同的服务器上。我需要根据其中的环境动态更改我的Silverlight客户端上的端点地址。当我尝试通过代码更改地址或手动更新客户端配置文件时,我目前正在获取非常详细的404错误(讽刺)。Silverlight 3 WCF多服务器

但是,当我右键单击服务引用并转到在我的客户端上配置服务时,我可以更改地址并且它可以工作。

我有以下服务。

<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()被吐出的地址是存在的,我可以使用浏览器来验证它是否存在(更不用说我可以连接t了它使用wcftestclient)。

例外:

{System.ServiceModel.CommunicationException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound. at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult) at System.Net.Browser.BrowserHttpWebRequest.<>c_DisplayClass5.b_4(Object sendState) at System.Net.Browser.AsyncHelper.<>c_DisplayClass4.b_1(Object sendState) --- End of inner exception stack trace --- at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state) at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result) --- End of inner exception stack trace --- at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result) at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) at System.ServiceModel.ClientBase 1.ChannelBase 1.EndInvoke(String methodName, Object[] args, IAsyncResult result) at EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.DrawingServiceClientChannel.EndGetEvalAreaDrawing(IAsyncResult result) at EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.EvaluaionAncillaryControl.EvalDrawingService.IDrawingService.EndGetEvalAreaDrawing(IAsyncResult result) at EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.OnEndGetEvalAreaDrawing(IAsyncResult result) at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)}

+0

当您在config中更改了端点地址时发生了什么?这应该工作,我相信 – Richard 2011-03-30 20:08:38

+0

@理查德 - 看到我的编辑,谢谢。 – AGoodDisplayName 2011-03-30 20:17:29

+0

两个建议 - 请发布确切的错误消息,你可能想使用提琴手来查看失败的请求。 – rboarman 2011-04-11 19:52:47

回答

0

我发现这些看起来有前途:

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

我想这就是它......你给我的第一个链接有一个例子,我开始使用它,它向我展示了我的方式的错误......我没有意识到我需要追加一个“/服务”到我的地址的末尾。这是在我的服务中指定的,但我认为这是我的.svc文件的relatvie地址...它不是(为什么它没有跨越我的想法?)。我必须再测试一次,但如果它在其他机器上工作,我会在明天奖赏你的赏金(看起来没有问题)。谢谢! – AGoodDisplayName 2011-04-11 22:44:28

+0

祝你好运,如果你需要更多的帮助,欢迎你 – rboarman 2011-04-11 22:51:01

1

(分辨率) 我能找到通过观察什么在从@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文件,但显然我错了。