如何获取WCF Web服务请求的XML SOAP请求?

我在代码中调用这个Web服务,我想看看XML,但是我找不到一个暴露它的属性。

我想你的意思是你想在客户端看到XML,而不是在服务器上跟踪它。 在这种情况下,您的回答是在上面链接的问题中,以及如何在客户端上检查或修改邮件 。 但是,由于该文章的.NET 4版本缺lessC#,而.NET 3.5的例子中有一些混淆(如果不是bug),这里就是为了您的目的而扩展的。

您可以使用IClientMessageInspector在消息出来之前拦截该消息:

using System.ServiceModel.Dispatcher; public class MyMessageInspector : IClientMessageInspector { } 

该接口中的方法BeforeSendRequestAfterReceiveReply使您可以访问请求和答复。 要使用检查器,您需要将其添加到IEndpointBehavior中 :

 using System.ServiceModel.Description; public class InspectorBehavior : IEndpointBehavior { public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new MyMessageInspector()); } } 

除非您也想使用它们的function,否则可以将该接口的其他方法保留为空实现。 阅读如何获取更多细节。

在实例化客户端之后,将行为添加到端点。 使用示例WCF项目中的默认名称:

 ServiceReference1.Service1Client client = new ServiceReference1.Service1Client(); client.Endpoint.Behaviors.Add(new InspectorBehavior()); client.GetData(123); 

MyMessageInspector.BeforeSendRequest()设置断点 request.ToString()被重载以显示XML。

如果你要操纵这些信息,你必须处理这个信息的副本。 有关详细信息,请参阅使用消息类 。

感谢Zach Bonham在寻找这些链接的另一个问题上的回答 。

选项1

使用消息跟踪/日志logging

看看这里和这里 。


选项2

您总是可以使用Fiddler来查看HTTP请求和响应。


选项3

使用System.Net跟踪 。

 OperationContext.Current.RequestContext.RequestMessage 

这个上下文在请求处理期间是可访问的服务器端。 这对单向操作不起作用

简单地说,我们可以跟踪请求消息。

 OperationContext context = OperationContext.Current; if (context != null && context.RequestContext != null) { Message msg = context.RequestContext.RequestMessage; string reqXML = msg.ToString(); } 

我在ASP.NET兼容模式下使用以下解决scheme进行IIS托pipe。 感谢Rodney Viana的MSDN博客 。

在appSettings下的web.config中添加以下内容:

 <add key="LogPath" value="C:\\logpath" /> <add key="LogRequestResponse" value="true" /> 

用下面的代码replace你的global.asax.cs(也修复命名空间名称):

 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.SessionState; using System.Text; using System.IO; using System.Configuration; namespace Yournamespace { public class Global : System.Web.HttpApplication { protected static bool LogFlag; protected static string fileNameBase; protected static string ext = "log"; // One file name per day protected string FileName { get { return String.Format("{0}{1}.{2}", fileNameBase, DateTime.Now.ToString("yyyy-MM-dd"), ext); } } protected void Application_Start(object sender, EventArgs e) { LogFlag = bool.Parse(ConfigurationManager.AppSettings["LogRequestResponse"].ToString()); fileNameBase = ConfigurationManager.AppSettings["LogPath"].ToString() + @"\C5API-"; } protected void Session_Start(object sender, EventArgs e) { } protected void Application_BeginRequest(object sender, EventArgs e) { if (LogFlag) { // Creates a unique id to match Rquests with Responses string id = String.Format("Id: {0} Uri: {1}", Guid.NewGuid(), Request.Url); FilterSaveLog input = new FilterSaveLog(HttpContext.Current, Request.Filter, FileName, id); Request.Filter = input; input.SetFilter(false); FilterSaveLog output = new FilterSaveLog(HttpContext.Current, Response.Filter, FileName, id); output.SetFilter(true); Response.Filter = output; } } protected void Application_AuthenticateRequest(object sender, EventArgs e) { } protected void Application_Error(object sender, EventArgs e) { } protected void Session_End(object sender, EventArgs e) { } protected void Application_End(object sender, EventArgs e) { } } class FilterSaveLog : Stream { protected static string fileNameGlobal = null; protected string fileName = null; protected static object writeLock = null; protected Stream sinkStream; protected bool inDisk; protected bool isClosed; protected string id; protected bool isResponse; protected HttpContext context; public FilterSaveLog(HttpContext Context, Stream Sink, string FileName, string Id) { // One lock per file name if (String.IsNullOrWhiteSpace(fileNameGlobal) || fileNameGlobal.ToUpper() != fileNameGlobal.ToUpper()) { fileNameGlobal = FileName; writeLock = new object(); } context = Context; fileName = FileName; id = Id; sinkStream = Sink; inDisk = false; isClosed = false; } public void SetFilter(bool IsResponse) { isResponse = IsResponse; id = (isResponse ? "Reponse " : "Request ") + id; // // For Request only read the incoming stream and log it as it will not be "filtered" for a WCF request // if (!IsResponse) { AppendToFile(String.Format("at {0} --------------------------------------------", DateTime.Now)); AppendToFile(id); if (context.Request.InputStream.Length > 0) { context.Request.InputStream.Position = 0; byte[] rawBytes = new byte[context.Request.InputStream.Length]; context.Request.InputStream.Read(rawBytes, 0, rawBytes.Length); context.Request.InputStream.Position = 0; AppendToFile(rawBytes); } else { AppendToFile("(no body)"); } } } public void AppendToFile(string Text) { byte[] strArray = Encoding.UTF8.GetBytes(Text); AppendToFile(strArray); } public void AppendToFile(byte[] RawBytes) { bool myLock = System.Threading.Monitor.TryEnter(writeLock, 100); if (myLock) { try { using (FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { stream.Position = stream.Length; stream.Write(RawBytes, 0, RawBytes.Length); stream.WriteByte(13); stream.WriteByte(10); } } catch (Exception ex) { string str = string.Format("Unable to create log. Type: {0} Message: {1}\nStack:{2}", ex, ex.Message, ex.StackTrace); System.Diagnostics.Debug.WriteLine(str); System.Diagnostics.Debug.Flush(); } finally { System.Threading.Monitor.Exit(writeLock); } } } public override bool CanRead { get { return sinkStream.CanRead; } } public override bool CanSeek { get { return sinkStream.CanSeek; } } public override bool CanWrite { get { return sinkStream.CanWrite; } } public override long Length { get { return sinkStream.Length; } } public override long Position { get { return sinkStream.Position; } set { sinkStream.Position = value; } } // // For WCF this code will never be reached // public override int Read(byte[] buffer, int offset, int count) { int c = sinkStream.Read(buffer, offset, count); return c; } public override long Seek(long offset, System.IO.SeekOrigin direction) { return sinkStream.Seek(offset, direction); } public override void SetLength(long length) { sinkStream.SetLength(length); } public override void Close() { sinkStream.Close(); isClosed = true; } public override void Flush() { sinkStream.Flush(); } // For streamed responses (ie not buffered) there will be more than one Response (but the id will match the Request) public override void Write(byte[] buffer, int offset, int count) { sinkStream.Write(buffer, offset, count); AppendToFile(String.Format("at {0} --------------------------------------------", DateTime.Now)); AppendToFile(id); AppendToFile(buffer); } } } 

它应该使用请求和响应XML在文件夹LogPath中创build日志文件。