如何在WCF自定义行为中动态更改URL

类定义如下:

public class BizTalkRESTTransmitHandler : IClientMessageInspector

我是这种签名的方法:

public object BeforeSendRequest(ref Message request, IClientChannel channel)

所以我认为我需要操纵通道对象。

原因是这是在BizTalk 2010 SendPort中使用以支持JSON。 我迄今为止尝试过:

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; 

}

上面给出了编译错误:“System.ServiceModel.EndpointAddress.Uri”不能被分配给 - 它只准备好了“RemoteAddress似乎也是只读的。

我引用了这些问题,但他们不使用通道对象。 在ASP.NET中为Url.AbsoluteUri分配一个URL,并在运行时WCF更改端点地址但是他们似乎没有处理通道对象。

更新1:我尝试了以下内容:

//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 

但它给了这个错误:System.InvalidOperationException:尝试获取IClientChannel的合同类型,但该类型不是ServiceContract,也不继承ServiceContract。


IClientMessageInspector不是控制Channel的正确位置,您应该使用IEndpointBehavior代替:

来自MSDN

实现可用于扩展服务或客户端应用程序中端点的运行时行为的方法。

这是一个简单的例子:

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

在这里,您可以阅读关于IEndpointBehavior的Carlos Figueira的优秀帖子:https: IEndpointBehavior

另一种选择是实现一个简单的WCF路由,这里是一个例子的链接:WCF REST服务URL路由基于查询参数

希望能帮助到你。


使用接口IEndpointBehavior,您将可以访问公开ServiceEndPoint实例的ApplyClientBehavior方法。 现在您可以通过定义一个新的EndpointAddress实例来更改Address的值。

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

我可能有点晚,但锄头它有点帮助。

我最近有一个类似的目标(也与biztalk有关),我需要根据邮件上发送的某些值更改网址。 我尝试使用ApplyDispatchBehavior方法,但它从来没有被调用,而且我也看不到如何从这里访问消息,所以我开始查看方法BeforeSendRequest(在Inspector类中)。

这是我想到的:

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

所以,我发现,搞砸了request.Headers.To我可以改变端点。

我在收到邮件内容和互联网上的大多数示例(显示使用MessageBuffer.CreateNavigator或Message.GetBody <string>时总是抛出一个我无法解析的表达式)时遇到了几个问题,它们不会给我biztalk消息,但而不是肥皂信息?......不知道,但它有一个节点头部,身体和身体内部有一些base64字符串,这不是我的biztalk消息。

另外,正如你在Convert.FromBase64String(reqAux.ToString().Replace("<Binary>", "").Replace("</Binary>", ""))中所看到的,我必须做这个丑陋的替换。 我不明白为什么这会出现在base64中,可能是一些WCF配置?,但通过这样做,我可以找到我的价值。

注意:我没有完全测试过这个,但到目前为止,它和我的例子一样。

顺便说一句,关于什么我可以切换我的MemoryStream,所以它成为一个更流的解决方案?

链接地址: http://www.djcxy.com/p/36033.html

上一篇: How Dynamically change URL in a WCF Custom Behavior

下一篇: defined functions in R?