Get SOAP Message before sending it to the WebService in .NET

南笙酒味 提交于 2019-12-17 18:39:25

问题


I'm calling an external HTTPS webservice.

In order to check what is wrong, the owner needs the SOAP request I'm sending.

I have a web reference and the generated proxy class generated by VS 2008...

Is there a way to see the SOAP message just before sending it?

I'm thinking in some .net code... because the Sniffers I tried didn't "see" the webservice invocation don't know why.


回答1:


What you need is a SoapExtension. There's quite a few good examples here:

How do I get access to SOAP response

Getting RAW Soap Data from a Web Reference Client running in ASP.net

XML Parse error while processing the SOAP response

One of the articles linked to: http://msdn.microsoft.com/en-us/magazine/cc164007.aspx

Also search SO for: https://stackoverflow.com/search?q=SoapExtension




回答2:


You can simply serialize the request object, before subtmit, like this:

var sreq = new SomeSoapRequest();

// ... fill in here ...

var serxml = new System.Xml.Serialization.XmlSerializer(sreq.GetType());
var ms = new MemoryStream();
serxml.Serialize(ms, sreq);
string xml = Encoding.UTF8.GetString(ms.ToArray());

// in xml string you have SOAP request



回答3:


You can use IClientMEssageInspector and IEndpointBehavior to fullfill this. I found using this way can capture the exact soap request likely as the fiddler one:

Create a class like this in the same project:

public class ClientMessageInspector : System.ServiceModel.Dispatcher.IClientMessageInspector
    {
        #region IClientMessageInspector Members
        public string LastRequestXml { get; private set; }

        public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {

        }

        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {
            string requestHeaderName = request.Headers.Action.Replace("urn:#",string.Empty);
            LastRequestXml = request.ToString();
            string serializedRequestFile = string.Format(requestHeaderName + "_request_{0}.xml", DateTime.Now.ToString("yyyyMMddHHmmss"));
            string exportedFolder = ConfigurationManager.AppSettings["SubmittedRequestXmLocation"];
            printSoapRequest(request, exportedFolder, serializedRequestFile);

            return request;
        }

        public void printSoapRequest(System.ServiceModel.Channels.Message request, string exportedFolder, string fileName)
        {
            if (exportedFolder.Equals(string.Empty))
                return;

            if (!Directory.Exists(exportedFolder))
            {
                Directory.CreateDirectory(exportedFolder);
            }
            string exportedFile = string.Format("{0}\\{1}", exportedFolder, fileName);
            if (File.Exists(exportedFile))
            {
                File.Delete(exportedFile);
            }

            string strRequestXML = request.ToString();
            XDocument xDoc = XDocument.Parse(strRequestXML);
            XmlWriter xw = XmlWriter.Create(exportedFile);
            xDoc.Save(xw);
            xw.Flush();
            xw.Close();
            LogOutput("Request file exported: " + exportedFile);

        }

    }

    public class CustomInspectorBehavior : IEndpointBehavior
    {
        private readonly ClientMessageInspector clientMessageInspector = new ClientMessageInspector();

        public string LastRequestXml
        {
            get { return clientMessageInspector.LastRequestXml; }
        }

        public string LastResponseXml
        {
            get { return clientMessageInspector.LastRequestXml; }
        }

        public void AddBindingParameters(
            ServiceEndpoint endpoint,
            System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(clientMessageInspector);
        }
    }

Then you can call it like the following:

ProxyClass _class = new ProxyClass();
var requestInterceptor = new CustomInspectorBehavior();
           _client.Endpoint.Behaviors.Add(requestInterceptor);

When you call the service method, it will automatically execute the interceptor and print the output. Using this way you can also manipulate the soap message before sending to the server!




回答4:


If you work in a more restricted environment and don't have the luxury of using an application like Fiddler, you can do the following:

  1. Generate your web reference as usual.
  2. Write code to perform whatever web method call you're going to me.
  3. Create a new ASP .NET project of your choice, I went with MVC 4.
  4. Create a handler or controller/action, and extract the request stream like this:

using (var reader = new System.IO.StreamReader(Request.InputStream)) { result = reader.ReadToEnd(); }

  1. Put a breakpoint on it and run it in debug mode.
  2. On your client, set the Url of the SOAP request to your new controller/handler.
  3. Run your client. You should catch the breakpoint on your web app with your SOAP message.

It's not an ideal or pretty solution, but if you are working in a moderately restricted environment, it gets the job done.



来源:https://stackoverflow.com/questions/461744/get-soap-message-before-sending-it-to-the-webservice-in-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!