#c# #.net #.net-core #dotnet-httpclient
#c# #.net #.net-core #dotnet-httpclient
Вопрос:
Я хочу сгенерировать содержимое Http-запроса, но фактически не выполнить запрос. Я просто хочу сохранить его на диск.
Вот как я это делаю, и я не большой поклонник. В настоящее время просто регистрируется в регистраторе тестов xUnit. Есть ли лучший способ зарегистрировать запрос без его фактического выполнения? Самое большое, что мне не нравится, это то, что мой подход к захвату запроса выполняет форматирование, которое на самом деле может быть неправильным во всех случаях.
public async void GenerateWithHeader()
{
using (MultipartFormDataContent content = GenerateMultipartContent())
{
HttpClient c = new HttpClient(new RequestCaptureHandler(new HttpClientHandler(), this.output));
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Post, "http://test.ca");
//we want xml back
msg.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml"));
msg.Content = content;
try
{
await c.SendAsync(msg);
}
catch (InvalidOperationException)
{
//suppress it. we don't actually want to make the request
}
}
}
public class RequestCaptureHandler : DelegatingHandler
{
private readonly ITestOutputHelper output;
public RequestCaptureHandler(HttpMessageHandler innerHandler, ITestOutputHelper output)
: base(innerHandler)
{
this.output = output;
}
protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
//The Request-Line begins with a method token, followed by the Request-URI and the protocol version, and ending with CRLF.The elements are separated by space characters.
//Request-Line = Method <space> Request-URI <space> HTTP-Version CRLF
this.output.WriteLine($"{request.Method} {request.RequestUri.ToString()} {request.Version}");
//Zero or more header (General|Request|Entity) fields followed by CRLF
foreach (var h in request.Headers)
{
this.output.WriteLine($"{h.Key}: {string.Join(' ', h.Value)}");
}
foreach (var h in request.Content.Headers)
{
this.output.WriteLine($"{h.Key}: {string.Join(' ', h.Value)}");
}
//An empty line (i.e., a line with nothing preceding the CRLF) indicating the end of the header fields
this.output.WriteLine("");
//Optionally a message-body
if (request.Content != null)
{
this.output.WriteLine(await request.Content.ReadAsStringAsync());
}
//Don't actually want to make the request. This will cause an InvalidOperationException when the SendAsync function of HttpClient is called.
return null;
}
}
Комментарии:
1. На самом деле довольно просто создать его самостоятельно. Структура http хорошо документирована и буквально содержит только новые строки с данными. Все, что вам нужно, это StringBuilder, использование клиента добавит гораздо больше накладных расходов, чем вам нужно. Кроме того, объекты client и request не предназначены для использования таким образом, хотя объект запроса может сериализоваться так, как вы хотите.
2. если вы хотите сохранять только запросы, а не выполнять, почему бы не сохранить сами объекты HttpRequestMessage ?. кстати, стоит отметить, что один и тот же экземпляр HttpRequestMessage не может быть отправлен несколько раз
3. Если вы намереваетесь проверить запрос только для целей отладки, я рекомендую использовать Fiddler telerik.com/fiddler и настройте свое приложение, чтобы использовать его в качестве прокси-сервера learn.microsoft.com/en-us/dotnet/framework/configure-apps /. … Если нет, вы можете реализовать другое веб-приложение и настроить это приложение на использование другого в качестве прокси, затем вы можете использовать новое веб-приложение для проверки необработанных запросов.
4. @Bakurits — HttpRequestMessage не включает строку запроса или заголовки запроса.