In my WinForms app I want to see raw request/response data when it interacts with webApi. I need to show request/response in UI RichTextBoxes. To do this I set up my HttpClient as follows:
private HttpClient client;
private void CreateService()
{
client = new HttpClient(new LoggingHandler(new HttpClientHandler(), this))
{
BaseAddress = new Uri(this._URI)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
My Logging Handler:
public class LoggingHandler : DelegatingHandler
{
private SimplySignRestClientAsync _client;
public LoggingHandler(HttpMessageHandler innerHandler, SimplySignRestClientAsync client) : base(innerHandler)
{
this._client = client;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string p_Request = "";
if (_client._updateRequest != null)
{
p_Request = request.ToString();
if (request.Content != null)
{
p_Request += "\n\nContent:\n" + FormatJsonString(await request.Content.ReadAsStringAsync());
}
//_client._request.Text = p_Request; << this works but causes a cross-thread exception in debug only
SetText(p_Request); << This deadlocks the UI
}
return response;
}
delegate void SetTextCallback(string text);
private void SetText(string text)
{
if (_client._request.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
_client._response.Invoke(d, new object[] { text });
}
else
{
_client._request.Text = text;
}
}
}
If i try to access richtextbox directly it works only when i execute app without debugging. But during debug it comes up with cross-thread exception.
This is how I call httpClient:
//This is how the original call gets initiated from UI
private void uiLogin_Click(object sender, EventArgs e)
{
Agent resp = Client.Login(new Credentials(uiUsername.Text, uiPassword.Text));
uiAuthToken.Text = Client.getAuthToken();
}
//this method has to stay synchronous, but it in turn calls an async method below
public Agent Login(Credentials loginInfo)
{
var task = Task.Run(async () => await LoginAsync(loginInfo));
return task.Result.Content; <<< this is where the application stops if i hit pause during debug when deadlock happens
}
//
async public Task<RestResponse<Agent>> LoginAsync(Credentials loginInfo)
{
HttpResponseMessage response = await client.PostAsJsonAsync(this._URI + "api/users/login", loginInfo);
var content = await response.Content.ReadAsStringAsync();
RestResponse<Agent> respAgent respAgent = JsonConvert.DeserializeObject<RestResponse<Agent>>(content);
return respAgent;
}
as I understand my "return task.Result.Content" blocks the UI thread and "_client._response.Invoke(d, new object[] { text });" is waiting for that to unblock causing deadlock. But I'm not sure how to make invoke wait too.