Трассировка вызова WCF от клиента
Я создал клиентское приложение Windows Forms, которое делает вызов WCF. Я хотел бы иметь возможность отображать фактический запрос и ответ, включая заголовок SOAP и информацию о POST/Get, из приложения. Есть ли способ настроить прослушиватель трассировки на клиенте и использовать его внутри клиента, отображая содержимое в текстовом поле?
Я настроил трассировку, которая выводит сообщения в файл. Эта конфигурация находится в моем клиентском приложении, поэтому она регистрирует все вызовы, которые она делает, в службу wcf и ответ. Таким образом, источники были добавлены, и для каждого источника есть XmlTraceListener, который обрабатывает запись в файл журнала xml. Теперь я хочу использовать прослушиватель трассировки из самого клиентского приложения и записать в блок управления текстовыми полями.
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All">
<listeners>
<add name="xmlTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging"
switchValue="All">
<listeners>
<add name="xmlTraceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xmlTraceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="ClientLogBasic.svclog" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
<!-- child of the <system.serviceModel> element -->
<diagnostics>
<messageLogging maxMessagesToLog="10000"
logEntireMessage="true"
logMessagesAtServiceLevel="true"
logMalformedMessages="true"
logMessagesAtTransportLevel="true">
<filters>
<clear/>
</filters>
</messageLogging>
</diagnostics>
Итак, теперь, когда у меня работает ведение журнала сообщений, я создаю свой собственный прослушиватель трассировки, который может писать в текстовое поле:
public class MyTraceListender : System.Diagnostics.TraceListener
{
private TextBox txt_m;
public MyTraceListender(TextBox txt)
: base()
{
txt_m = txt;
}
private delegate void delWrite(string sText);
public override void Write(string message)
{
txt_m.Invoke(new delWrite(AsyncWrite), message);
}
public override void WriteLine(string message)
{
this.Write(message + System.Environment.NewLine);
}
private void AsyncWrite(string sMessage)
{
this.txt_m.AppendText(sMessage);
}
}
Теперь, когда у меня есть прослушиватель трассировки, я хочу попробовать использовать его из клиентского приложения Windows Forms.
public partial class Form1 : Form
{
private MyTraceListender listener_m;
public Form1()
{
InitializeComponent();
listener_m = new MyTraceListender(this.txtOutput);
System.Diagnostics.Trace.Listeners.Add(listener_m);
}
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
string sValue = client.GetData(1234);
}
}
На этом этапе я все еще не вижу входа в элемент управления текстовым полем. Я думаю, что слушатель не связан с источником, поэтому я попробовал следующее:
public partial class Form1 : Form
{
private MyTraceListender listener_m;
public static System.Diagnostics.TraceSource source = new System.Diagnostics.TraceSource("System.ServiceModel.MessageLogging", System.Diagnostics.SourceLevels.All);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
string sValue = client.GetData(1234);
}
private void Form1_Load(object sender, EventArgs e)
{
listener_m = new MyTraceListender("test", this.txtOutput);
source.Listeners.Add(listener_m);
}
}
После этого все сообщения не записываются в текстовое поле формы. Они записываются в файл через XmlTraceListener, поэтому я предполагаю, что проблема заключается в том, как я добавляю свой пользовательский прослушиватель через System.Diagnostics.Trace.Listeners.Add(). Это правильный подход?
Ответы
Ответ 1
Это решение в основном через app.config. Дайте мне знать, если вы предпочитаете решение на основе кода.
В app.config добавьте ваш слушатель в список общих слушателей, а также слушатель для источника ведения журнала сообщений. В списке "listeners" имя должно совпадать с именем позже в списке "sharedListeners". В списке "sharedListeners" "тип" должен включать полное имя класса с пространством имен, а также имя сборки:
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="All">
<listeners>
<add name="xmlTraceListener"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="All">
<listeners>
<add name="xmlTraceListener"/>
<add name="textBoxListener"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xmlTraceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="ClientLogBasic.svclog"/>
<add name="textBoxListener" type="WinTransmitterClient.MyTraceListener, WinTransmitterClient" initializeData=""/>
</sharedListeners>
<trace autoflush="true"/>
Поскольку MyTraceListener будет создан каркасом, его конструктор должен соответствовать базовому классу. Поэтому вместо этого создайте текстовое поле как свойство, которое можно установить при необходимости.
В MyTraceListener.cs:
public class MyTraceListener : System.Diagnostics.TraceListener
{
public TextBox txt_m
{
get;set;
}
public MyTraceListener()
: base()
{}
// rest as before ...
В Form1.cs возьмите пользовательский прослушиватель после создания клиента и установите текстовое поле. Никакой другой код не требуется. Это весь Form1.cs, исключая строки "using" и "namespace":
public partial class Form1 : Form
{
public static System.Diagnostics.TraceSource source = new System.Diagnostics.TraceSource("System.ServiceModel.MessageLogging", System.Diagnostics.SourceLevels.All);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.ContactManagerTextServiceClient client = new ServiceReference1.ContactManagerTextServiceClient();
// identifier in quotes must match name from config file
MyTraceListener mtl = source.Listeners["textBoxListener"] as MyTraceListener;
// of course this doesn't need to be done at every button click, but you get the idea
mtl.txt_m = this.txtOutput;
string sValue = client.GetData(1234);
}
}
Ответ 2
Отредактируйте файл конфигурации с помощью редактора конфигурации WCF и включите трассировку, как показано ниже.
![enter image description here]()
Ответ 3
Попробуйте создать инспектор сообщений. На стороне клиента вам придется реализовать IClientMessageInspector
, который позволит вам перехватить сообщение до его отправки, а также ответ, полученный до передачи его в приложение. Вы найдете более подробную информацию о MSDN