2011-03-30 141 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文件,但顯然我錯了。