简体   繁体   English

使用XML调用WCF服务

[英]Call WCF service with XML

I'm trying to call a WCF service. 我正在尝试调用WCF服务。

However, I have the request body as an XML document. 但是,我将请求正文作为XML文档。

So for instance, instead of this 因此,例如,代替这个

ListProductsRequest request = new ListProductsRequest();
request.Query = new RootQuery();
request.Query.Product = "milk";
request.Query.Group = "dairy";

ListProductsPortType client = new ListProductsPortTypeClient();
ListProductsResponse response = client.ListProducts(request);

I wanna do this: 我想这样做:

String xml = "<Root xmlns=\"urn:ns\"><Query><Group>dairy</Group><Product>milk</Product></Query></Root>";
var request = // read in to XmlReader or XmlDocument or whatever
ListProductsPortType client = new ListProductsPortTypeClient();
var response = client.ListProducts(request);

Is there a way to use the generated proxy, with the advantage of having the data layer security and transport handled for me, but without using the proxy objects? 有没有一种方法可以使用生成的代理,而该代理具有为我处理数据层安全性和传输但不使用代理对象的优点?

Thanks, Brecht 谢谢,布莱希特

I don't think you can call a WCF service and passing what you want. 我认为您不能调用WCF服务并传递您想要的东西。

The method ListProducts only accept a ListProductsRequest object. ListProducts方法仅接受ListProductsRequest对象。 So you have to create this kind of object. 因此,您必须创建这种对象。

String xml = "<Root xmlns=\"urn:ns\"><Query><Group>dairy</Group><Product>milk</Product></Query></Root>";
ListProductsRequest request = MappingObject(xml); 
ListProductsPortType client = new ListProductsPortTypeClient();
var response = client.ListProducts(request);

And in the Mapping method you can work with your XML to create an ListproductRequest. 在Mapping方法中,您可以使用XML创建ListproductRequest。

I don't know if there is another way to do this. 我不知道是否还有其他方法可以做到这一点。

I got this far, thanks to 2GDev's comment. 由于2GDev的评论,我到现在为止。 Code without handling exceptions or abnormal situations properly. 没有正确处理异常或异常情况的代码。

This way I can use the generated stub's endpoint (and thus reuse the config etc.) 这样,我可以使用生成的存根的终结点(并因此重复使用配置等)。

    public void CallWs()
    {
        WsdlRDListProductsPortTypeClient client = new WsdlRDListProductsPortTypeClient();

        String req = "<Root xmlns=\"urn:ns\"><Query><Group>TV</Group><Product>TV</Product></Query></Root>";

        CallWs(client.Endpoint, "ListProducts", GetRequestXml(req));
    }

    public XmlElement CallWs(ServiceEndpoint endpoint, String operation, XmlElement request)
    {
        String soapAction = GetSoapAction(endpoint, operation);

        IChannelFactory<IRequestChannel> factory = null;

        try
        {
            factory = endpoint.Binding.BuildChannelFactory<IRequestChannel>();
            factory.Open();
            IRequestChannel channel = null;

            try
            {
                channel = factory.CreateChannel(endpoint.Address);
                channel.Open();

                Message requestMsg = Message.CreateMessage(endpoint.Binding.MessageVersion, soapAction, request);
                Message response = channel.Request(requestMsg);
                return response.GetBody<XmlElement>();
            }
            finally
            {
                if (channel != null)
                    channel.Close();
            }
        }
        finally
        {
            if (factory != null)
                factory.Close();
        }
    }

    private String GetSoapAction(ServiceEndpoint endpoint, String operation)
    {

        foreach (OperationDescription opD in endpoint.Contract.Operations)
        {
            if (opD.Name == operation)
            {
                foreach (MessageDescription msgD in opD.Messages)
                    if (msgD.Direction == MessageDirection.Input)
                    {
                        return msgD.Action;
                    }
            }

        }

        return null;
    }

When I try this with the basic ICalculator sample from msdn http://msdn.microsoft.com/en-us/library/ms734712.aspx 当我尝试使用msdn http://msdn.microsoft.com/zh-cn/library/ms734712.aspx的基本ICalculator示例进行此操作时

Which is secured with SPNego, I have to change this a bit, because then we need an IRequestSessionChannel instead of an IRequestChannel. 使用SPNego进行保护,我必须对此稍作更改,因为那时我们需要一个IRequestSessionChannel而不是IRequestChannel。

    public XmlElement CallWs(ServiceEndpoint endpoint, String operation, XmlElement request)
    {
        String soapAction = GetSoapAction(endpoint, operation);

        IChannelFactory<IRequestSessionChannel> factory = null;

        try
        {


            factory = endpoint.Binding.BuildChannelFactory<IRequestSessionChannel>();
            factory.Open();
            IRequestSessionChannel channel = null;

            try
            {
                channel = factory.CreateChannel(endpoint.Address);
                channel.Open();

                Message requestMsg = Message.CreateMessage(endpoint.Binding.MessageVersion, soapAction, request);

                Message response = channel.Request(requestMsg);
                return response.GetBody<XmlElement>();
            }
            finally
            {
                if (channel != null)
                    channel.Close();
            }
        }
        finally
        {
            if (factory != null)
                factory.Close();
        }
    }

It does do the negotiation, and a message seems to be sent, but unfortunately I now get the following error message: 它确实进行了协商,并且似乎发送了一条消息,但是不幸的是,我现在收到以下错误消息:

No signature message parts were specified for messages with the 'http://Microsoft.ServiceModel.Samples/ICalculator/Add' action.

I think you could use 我想你可以用

ListProductsRequest request = (ListProductsRequest) new XmlSerializer(
    typeof(ListProductsRequest)).Deserialize();

to create the corresponding object... 创建相应的对象...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM