in libraries/Microsoft.Bot.Builder.Dialogs.Adaptive/Actions/HttpRequest.cs [217:405]
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (options is CancellationToken)
{
throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
}
if (Disabled != null && Disabled.GetValue(dc.State))
{
return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
}
// This is injected for testing, and should not be used for anything else.
var client = dc.Context.TurnState.Get<HttpClient>();
var disposeHttpClient = false;
if (client == null)
{
disposeHttpClient = true;
//Note: this should also be analyzed once we start using HttpClientFactory.
#pragma warning disable CA2000 // Dispose objects before losing scope
client = new HttpClient();
#pragma warning restore CA2000 // Dispose objects before losing scope
}
try
{
var instanceBody = Body?.EvaluateExpression(dc.State);
var instanceHeaders = Headers == null ? null : Headers.ToDictionary(kv => kv.Key, kv => kv.Value.GetValue(dc.State));
var (instanceUrl, instanceUrlError) = Url.TryGetValue(dc.State);
if (instanceUrlError != null)
{
throw new ArgumentException(instanceUrlError);
}
using HttpRequestMessage request = new HttpRequestMessage(new System.Net.Http.HttpMethod(Method.ToString()), instanceUrl);
// Set headers
if (instanceHeaders != null)
{
foreach (var unit in instanceHeaders)
{
request.Headers.TryAddWithoutValidation(unit.Key, unit.Value);
}
}
request.Headers.TryAddWithoutValidation("user-agent", "Mozilla/5.0");
dynamic traceInfo = new JObject();
traceInfo.request = new JObject();
traceInfo.request.method = Method.ToString();
traceInfo.request.url = instanceUrl;
HttpResponseMessage response = null;
string contentType = ContentType?.GetValue(dc.State) ?? "application/json";
switch (Method)
{
case HttpMethod.POST:
if (instanceBody == null)
{
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
else
{
using var postContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType);
traceInfo.request.content = instanceBody.ToString();
request.Content = postContent;
traceInfo.request.headers = JObject.FromObject(request.Content.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
break;
case HttpMethod.PATCH:
if (instanceBody == null)
{
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
else
{
using var patchContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType);
request.Content = patchContent;
traceInfo.request.content = instanceBody.ToString();
traceInfo.request.headers = JObject.FromObject(request.Content.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
break;
case HttpMethod.PUT:
if (instanceBody == null)
{
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
else
{
using var putContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType);
traceInfo.request.content = instanceBody.ToString();
request.Content = putContent;
traceInfo.request.headers = JObject.FromObject(request.Content.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
break;
case HttpMethod.DELETE:
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
break;
case HttpMethod.GET:
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
break;
}
var requestResult = new Result(response.Headers)
{
StatusCode = (int)response.StatusCode,
ReasonPhrase = response.ReasonPhrase,
};
object content = (object)await response.Content.ReadAsStringAsync().ConfigureAwait(false);
switch (ResponseType.GetValue(dc.State))
{
case ResponseTypes.Activity:
var activity = JsonConvert.DeserializeObject<Activity>((string)content);
requestResult.Content = JObject.FromObject(activity);
await dc.Context.SendActivityAsync(activity, cancellationToken: cancellationToken).ConfigureAwait(false);
break;
case ResponseTypes.Activities:
var activities = JsonConvert.DeserializeObject<Activity[]>((string)content);
requestResult.Content = JArray.FromObject(activities);
await dc.Context.SendActivitiesAsync(activities, cancellationToken: cancellationToken).ConfigureAwait(false);
break;
case ResponseTypes.Json:
// Try set with JOjbect for further retrieving
try
{
content = JToken.Parse((string)content);
}
#pragma warning disable CA1031 // Do not catch general exception types (just stringify the content if we can't parse the content).
catch
#pragma warning restore CA1031 // Do not catch general exception types
{
content = content.ToString();
}
requestResult.Content = content;
break;
case ResponseTypes.Binary:
// Try to resolve binary data
var bytes = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
requestResult.Content = bytes;
break;
case ResponseTypes.None:
default:
break;
}
traceInfo.response = JObject.FromObject(requestResult);
// Write Trace Activity for the http request and response values
await dc.Context.TraceActivityAsync("HttpRequest", (object)traceInfo, valueType: "Microsoft.HttpRequest", label: Id).ConfigureAwait(false);
if (ResultProperty != null)
{
dc.State.SetValue(ResultProperty.GetValue(dc.State), requestResult);
}
// return the actionResult as the result of this operation
return await dc.EndDialogAsync(result: requestResult, cancellationToken: cancellationToken).ConfigureAwait(false);
}
finally
{
if (disposeHttpClient)
{
client.Dispose();
}
}
}