使用XML调用WCF服务

时间:2011-09-21 14:14:12

标签: c# wcf

我正在尝试调用WCF服务。

但是,我将请求正文作为XML文档。

例如,而不是这个

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

我想这样做:

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

有没有办法使用生成的代理,具有为我处理数据层安全性和传输的优势,但不使用代理对象?

谢谢, 布莱希特

3 个答案:

答案 0 :(得分:1)

我认为您不能调用WCF服务并传递您想要的内容。

方法ListProducts只接受ListProductsRequest对象。所以你必须创建这种对象。

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

在Mapping方法中,您可以使用XML来创建ListproductRequest。

我不知道是否还有其他方法可以做到这一点。

答案 1 :(得分:1)

我得到了这一点,感谢2GDev的评论。代码没有正确处理异常或异常情况。

这样我就可以使用生成的stub的端点(从而重用config等)。

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

当我尝试使用msdn的基本ICalculator样本时 http://msdn.microsoft.com/en-us/library/ms734712.aspx

使用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();
        }
    }

它确实进行了协商,似乎发送了一条消息,但遗憾的是我现在收到以下错误消息:

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

答案 2 :(得分:0)

我认为你可以使用

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

创建相应的对象......