2016-09-02 15 views
7

lớp được định nghĩa như sau:Làm thế nào Tự động thay đổi URL trong một hành vi WCF Tuỳ chỉnh

public class BizTalkRESTTransmitHandler : IClientMessageInspector 

Tôi là một phương pháp có chữ ký này:

public object BeforeSendRequest(ref Message request, IClientChannel channel) 

Vì vậy, tôi nghĩ rằng tôi cần phải thao tác kênh vật.

Lý do là điều này đang được sử dụng trong BizTalk 2010 SendPort để hỗ trợ JSON. Tôi cố gắng này cho đến nay:

if (channel.RemoteAddress.Uri.AbsoluteUri == "http://api-stage2.mypartner.com/rest/events/2/" 
    || channel.RemoteAddress.Uri.AbsoluteUri == "http://api.mypartner.com/rest/events/2/") 
{ 
    //TODO - "boxout" will become a variable obtained by parsing the message 
    Uri newUri = new Uri(channel.RemoteAddress.Uri.AbsoluteUri + "boxout"); 
    channel.RemoteAddress.Uri = newUri; 

} 

Trên cung cấp cho biên dịch báo lỗi: "System.ServiceModel.EndpointAddress.Uri" không thể được gán cho - nó đã sẵn sàng chỉ" RemoteAddress dường như chỉ đọc cũng

tôi đã tham khảo những câu hỏi này nhưng họ không sử dụng đối tượng kênh Assign a URL to Url.AbsoluteUri in ASP.NET, và WCF change endpoint address at runtime nhưng họ dường như không thể đối phó với đối tượng kênh

cập nhật 1:.. tôi thử như sau:

//try create new channel to change URL 
WebHttpBinding myBinding = new WebHttpBinding(); 
EndpointAddress myEndpoint = new EndpointAddress(newURL); 
ChannelFactory<IClientChannel> myChannelFactory = new ChannelFactory<IClientChannel>(myBinding, myEndpoint); //Change to you WCF interface 
IClientChannel myNewChannel = myChannelFactory.CreateChannel(); 
channel = myNewChannel; //replace the channel parm passed to us 

nhưng nó đã cho lỗi này: System.InvalidOperationException: Đã cố gắng để có được loại hợp đồng cho IClientChannel, nhưng kiểu đó không phải là một ServiceContract, cũng không thừa hưởng một ServiceContract.

+0

Điều gì tạo nên một kênh hoàn toàn mới như ở đây? Có vẻ như quá mức cần thiết. http://stackoverflow.com/questions/27782919/wcf-change-address-at-runtime-exception/27783784#27783784 – NealWalters

Trả lời

1

IClientMessageInspector không phải là nơi quyền thao tác các Kênh, bạn nên sử dụng IEndpointBehavior thay vì:

Từ MSDN

Implements methods that can be used to extend run-time behavior for an endpoint in either a service or client application.

Dưới đây là một ví dụ đơn giản:

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
{ 
    Uri endpointAddress = endpoint.Address.Uri; 
    string address = endpointAddress.ToString(); 

    if (address == "http://api-stage2.mypartner.com/rest/events/2/" 
    || address == "http://api.mypartner.com/rest/events/2/") 
    { 
     //TODO - "boxout" will become a variable obtained by parsing the message 
     Uri newUri = new Uri(address + "boxout"); 
     ServiceHostBase host = endpointDispatcher.ChannelDispatcher.Host; 
     ChannelDispatcher newDispatcher = this.CreateChannelDispatcher(host, endpoint, newUri); 
     host.ChannelDispatchers.Add(newDispatcher); 
    } 
} 

Ở đây bạn có thể đọc các bài tuyệt vời của Carlos Figueira về IEndpointBehavior: https://blogs.msdn.microsoft.com/carlosfigueira/2011/04/04/wcf-extensibility-iendpointbehavior/

lựa chọn khác là để thực hiện một Routing đơn giản với WCF, đây là liên kết với một ví dụ: WCF REST service url routing based on query parameters

Hy vọng nó giúp.

+0

Tiền thưởng được trao ... Nhưng thật đáng buồn, như tôi đã nói với người kia đã trả lời, Tôi cần thay đổi URL dựa trên dữ liệu trong tin nhắn của mình. Tôi đã thực hiện nó trong BizTalk Pipeline. – NealWalters

2

Sử dụng giao diện IEndpointBehavior, bạn sẽ có quyền truy cập vào phương thức ApplyClientBehavior, hiển thị trường hợp ServiceEndPoint. Bây giờ bạn có thể thay đổi giá trị cho Địa chỉ bằng cách xác định một cá thể EndpointAddress mới.

public class MyCustomEndpointBehavior : IEndpointBehavior 
{  
    public void AddBindingParameters(ServiceEndpoint serviceEndpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { 
    } 
    public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, System.ServiceModel.Dispatcher.ClientRuntime behavior) 
    { 
     serviceEndpoint.Address = new System.ServiceModel.EndpointAddress("http://mynewaddress.com"); 
    } 
    public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) 
    { 
    } 
    public void Validate(ServiceEndpoint serviceEndpoint) 
    { 
    } 
} 
+0

Tôi thấy rằng có lẽ sẽ làm việc cho một chữ; nhưng tôi đã không giải thích trong câu hỏi của tôi-URL cần một hậu tố dựa trên loại tin nhắn. Vì vậy, các tin nhắn dường như không có sẵn trong tin nhắn đó. [Tôi đã xây dựng một đường ống BizTalk làm điều đó, nhưng tôi muốn nó và chương trình JSON/Chuyển đổi, hơn là hai.] – NealWalters

0

Tôi có thể hơi muộn một chút nhưng cuốc nó sẽ giúp ích một chút.

Gần đây tôi đã có một mục tiêu tương tự (cũng liên quan đến biztalk), nơi tôi cần thay đổi url dựa trên một số giá trị được gửi trên thư. Tôi đã thử sử dụng phương thức ApplyDispatchBehavior nhưng nó không bao giờ được gọi và cũng có thể, tôi không thể xem cách truy cập thư từ đây vì vậy tôi bắt đầu xem xét phương thức BeforeSendRequest (trong lớp Inspector).

Dưới đây là những gì tôi đã đưa ra:

object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
     var queryDictionary = HttpUtility.ParseQueryString(request.Headers.To.Query); 
     string parameterValue = queryDictionary[this.BehaviourConfiguration.QueryParameter]; 

     //Only change parameter value if it exists 
     if (parameterValue != null) 
     { 
      MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue); 

      request = buffer.CreateMessage(); 

      //Necessary in order to read the message without having WCF throwing and error saying 
      //the messas was already read 
      var reqAux = buffer.CreateMessage(); 

      //For some reason the message comes in binary inside tags <Binary>MESSAGE</Binary> 
      using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(reqAux.ToString().Replace("<Binary>", "").Replace("</Binary>", "")))) 
      { 
       ms.Position = 0; 
       string val = ExtractNodeValueByXPath(ms, this.BehaviourConfiguration.FieldXpath); 

       queryDictionary.Set(this.BehaviourConfiguration.QueryParameter, DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + 
        this.BehaviourConfiguration.Message + (string.IsNullOrWhiteSpace(val) ? string.Empty : "_" + val) + ".xml"); 

       UriBuilder ub = new UriBuilder(request.Headers.To); 
       ub.Query = queryDictionary.ToString(); 
       request.Headers.To = ub.Uri; 
      } 
     } 

     return null; 
    } 

Vì vậy, tôi phát hiện ra rằng, can thiệp vào request.Headers.To tôi có thể thay đổi các thiết bị đầu cuối.

Tôi gặp phải một số sự cố khi nhận nội dung thư và hầu hết các ví dụ trên internet (hiển thị để sử dụng chuỗi MessageBuffer.CreateNavigator hoặc Message.GetBody <> luôn luôn không thể giải quyết) thông điệp biztalk nhưng thay vì thông điệp xà phòng? ... không chắc chắn nhưng nó có một tiêu đề nút, cơ thể và bên trong cơ thể có một số chuỗi base64 mà không phải là thông điệp biztalk của tôi.

Ngoài ra, như bạn có thể thấy trong Convert.FromBase64String(reqAux.ToString().Replace("<Binary>", "").Replace("</Binary>", "")), tôi phải làm điều này thay thế xấu xí. Tôi không không lý do tại sao điều này đến trong base64, có lẽ một số cấu hình WCF ?, Nhưng bằng cách làm điều đó, tôi có thể sau đó tìm giá trị của tôi.

LƯU Ý: Tôi chưa thử nghiệm đầy đủ tính năng này, nhưng cho đến nay nó đã hoạt động cho các ví dụ của tôi.

Nhân tiện, bất kỳ ý tưởng nào về việc tôi có thể chuyển đổi MemoryStream của mình để nó trở thành một giải pháp truyền trực tuyến hơn?

Các vấn đề liên quan