WCF 웹 서비스 요청의 XML SOAP 요청을 받으려면 어떻게 해야 합니까?
코드 내에서 이 웹 서비스를 호출하고 XML을 보고 싶은데 노출되는 속성을 찾을 수 없습니다.
서버에서 XML을 추적하는 것이 아니라 클라이언트에서 XML을 보고 싶다는 뜻이었던 것 같습니다.이 경우 위에 링크한 질문과 클라이언트의 메시지를 검사하거나 수정하는 방법에 답변이 있습니다.근데 그때부터.해당 기사의 NET 4 버전에는 C#이 없습니다.NET 3.5 예제에는 약간의 혼란이 있습니다(버그가 아닌 경우). 여기서는 사용자의 목적에 맞게 확장합니다.
IC 클라이언트 메시지를 사용하여 메시지가 나가기 전에 가로챌 수 있습니다.인스펙터:
using System.ServiceModel.Dispatcher;
public class MyMessageInspector : IClientMessageInspector
{ }
BeforeSendRequest
그리고.AfterReceiveReply
, 요청 및 회신에 대한 접근 권한을 부여합니다.검사기를 사용하려면 검사기를 끝점Behavior에 추가해야 합니다.
using System.ServiceModel.Description;
public class InspectorBehavior : IEndpointBehavior
{
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MyMessageInspector());
}
}
해당 인터페이스의 다른 메소드도 사용하지 않으려면 해당 인터페이스의 다른 메소드도 빈 구현으로 남겨둘 수 있습니다.자세한 내용은 사용 방법을 읽어 보십시오.
클라이언트를 인스턴스화한 후 엔드포인트에 동작을 추가합니다.샘플 WCF 프로젝트의 기본 이름 사용:
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
client.Endpoint.Behaviors.Add(new InspectorBehavior());
client.GetData(123);
합니다에 합니다.MyMessageInspector.BeforeSendRequest()
;request.ToString()
XML됩니다를 됩니다.
메시지를 조작하려면 메시지 사본 작업을 해야 합니다.자세한 내용은 메시지 클래스 사용을 참조하십시오.
이러한 링크를 찾기 위한 또 다른 질문에 대한 Zach Bonham의 답변에 감사드립니다.
옵션1
메시지 추적/로깅을 사용합니다.
옵션2
항상 Fiddler를 사용하여 HTTP 요청 및 응답을 볼 수 있습니다.
옵션3
간단히 요청 메시지를 다음과 같이 추적할 수 있습니다.
OperationContext context = OperationContext.Current;
if (context != null && context.RequestContext != null)
{
Message msg = context.RequestContext.RequestMessage;
string reqXML = msg.ToString();
}
저는 단지 킴벌리의 답변에 이것을 추가하고 싶었습니다.I EndpointBehavior 인터페이스가 필요로 하는 모든 메서드를 구현하지 않아 시간을 절약하고 컴파일 오류를 방지할 수 있습니다.
안부 전합니다
니키
/*
// This is just to illustrate how it can be implemented on an imperative declarared binding, channel and client.
string url = "SOME WCF URL";
BasicHttpBinding wsBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress(url);
ChannelFactory<ISomeService> channelFactory = new ChannelFactory<ISomeService>(wsBinding, endpointAddress);
channelFactory.Endpoint.Behaviors.Add(new InspectorBehavior());
ISomeService client = channelFactory.CreateChannel();
*/
public class InspectorBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
// No implementation necessary
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MyMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
// No implementation necessary
}
public void Validate(ServiceEndpoint endpoint)
{
// No implementation necessary
}
}
public class MyMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
// Do something with the SOAP request
string request = request.ToString();
return null;
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
// Do something with the SOAP reply
string replySoap = reply.ToString();
}
}
OperationContext.Current.RequestContext.RequestMessage
이 컨텍스트는 요청 처리 중에 접근 가능한 서버측입니다.이것은 단방향 작업에는 적용되지 않습니다.
저는 ASP에서 IIS 호스팅을 위해 아래 솔루션을 사용하고 있습니다.NET 호환 모드.로드니 비아나의 MSDN 블로그에 대한 크레딧.
appSettings에서 web.config에 다음을 추가합니다.
<add key="LogPath" value="C:\\logpath" />
<add key="LogRequestResponse" value="true" />
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 (i.e. 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 폴더에 로그 파일을 생성해야 합니다.
XML SOAP - 사용자 지정 메시지 인코더를 볼 수 있는 다른 방법이 있습니다.IC클라이언트 메시지와의 주요 차이점Inspector는 하위 레벨에서 작동하므로 잘못된 형식의 xml을 포함하여 원래 바이트 내용을 캡처합니다.
이 방법을 사용하여 추적을 구현하려면 사용자 지정 메시지 인코더를 새 바인딩 요소로 사용하여 표준 텍스트 MessageEncoding을 랩핑하고 해당 사용자 지정 바인딩을 구성의 끝점에 적용해야 합니다.
또한 제 프로젝트 - 래핑 textMessageEncoding, logging encoder, custom binding element 및 config - 에서 어떻게 했는지 볼 수 있습니다.
언급URL : https://stackoverflow.com/questions/5493639/how-do-i-get-the-xml-soap-request-of-an-wcf-web-service-request
'source' 카테고리의 다른 글
자바스크립트를 이용하여 Ctrl+V, Ctrl+C를 검출하는 방법? (0) | 2023.10.14 |
---|---|
리눅스 Perf 리포트 출력 이해 (0) | 2023.10.14 |
쿼리가 두 번째로 실행되면 더 빨리 실행됩니다. 이를 중지하려면 어떻게 해야 합니까? (0) | 2023.10.09 |
자바스크립트에서 이진수를 나타내는 "0b" 등이 있습니까? (0) | 2023.10.09 |
검색되지 않은 예외: Ajax Process의 메모리 부족 (0) | 2023.10.09 |