windowsphone restresponse restrequest example consume c# restsharp

c# - restresponse - restsharp github



RestSharp imprime encabezados de solicitud y respuesta sin procesar (7)

.net proporciona su propia y poderosa función de registro. Esto se puede activar a través del archivo de configuración.

Encontré este consejo here . John Sheehan apuntó a Cómo: configurar el artículo de rastreo de red . (una nota: edité la configuración proporcionada, apagué el registro de bajo nivel innecesario (para mí)).

<system.diagnostics> <sources> <source name="System.Net" tracemode="protocolonly" maxdatasize="1024"> <listeners> <add name="System.Net"/> </listeners> </source> <source name="System.Net.Cache"> <listeners> <add name="System.Net"/> </listeners> </source> <source name="System.Net.Http"> <listeners> <add name="System.Net"/> </listeners> </source> </sources> <switches> <add name="System.Net" value="Verbose"/> <add name="System.Net.Cache" value="Verbose"/> <add name="System.Net.Http" value="Verbose"/> <add name="System.Net.Sockets" value="Verbose"/> <add name="System.Net.WebSockets" value="Verbose"/> </switches> <sharedListeners> <add name="System.Net" type="System.Diagnostics.TextWriterTraceListener" initializeData="network.log" /> </sharedListeners> <trace autoflush="true"/> </system.diagnostics>

Estoy usando RestSharp para hacer llamadas a un servicio web. Todo está bien, pero me preguntaba si sería posible imprimir los encabezados de solicitud en bruto y el cuerpo que se envía y los encabezados de respuesta sin procesar y el cuerpo de respuesta que vuelve.

Este es mi código donde creo una solicitud y recibo una respuesta

public static TResponse ExecutePostCall<TResponse, TRequest>(String url, TRequest requestData, string token= "") where TResponse : new() { RestRequest request = new RestRequest(url, Method.POST); if (!string.IsNullOrWhiteSpace(token)) { request.AddHeader("TOKEN", token); } request.RequestFormat = DataFormat.Json; request.AddBody(requestData); // print raw request here var response = _restClient.Execute<TResponse>(request); // print raw response here return response.Data; }

Entonces, ¿sería posible imprimir la solicitud y respuesta sin procesar?


Acabo de encontrar el código a continuación en los ejemplos de RestSharp. Le permite imprimir su respuesta sin procesar.

client.ExecuteAsync(request, response => { Console.WriteLine(response.Content); });


Como solución parcial, puede usar el método BuildUri de BuildUri :

var response = client.Execute(request); if (response.StatusCode != HttpStatusCode.OK) throw new Exception($"Failed to send request: {client.BuildUri(request)}");


Como ya sabemos, RestSharp no proporciona un mecanismo para lograr exactamente lo que usted desea, y la activación del rastreo .Net es un poco excesivo para IMO.

Para fines de registro (depuración) (algo que puedo dejar activado por un tiempo en PROD, por ejemplo), he encontrado que este enfoque es muy útil (aunque tiene algunos detalles sobre cómo llamarlo, lea debajo del código):

private void LogRequest(IRestRequest request, IRestResponse response, long durationMs) { var requestToLog = new { resource = request.Resource, // Parameters are custom anonymous objects in order to have the parameter type as a nice string // otherwise it will just show the enum value parameters = request.Parameters.Select(parameter => new { name = parameter.Name, value = parameter.Value, type = parameter.Type.ToString() }), // ToString() here to have the method as a nice string otherwise it will just show the enum value method = request.Method.ToString(), // This will generate the actual Uri used in the request uri = _restClient.BuildUri(request), }; var responseToLog = new { statusCode = response.StatusCode, content = response.Content, headers = response.Headers, // The Uri that actually responded (could be different from the requestUri if a redirection occurred) responseUri = response.ResponseUri, errorMessage = response.ErrorMessage, }; Trace.Write(string.Format("Request completed in {0} ms, Request: {1}, Response: {2}", durationMs, JsonConvert.SerializeObject(requestToLog), JsonConvert.SerializeObject(responseToLog))); }

Cosas a tener en cuenta:

  • Encabezados, segmentos de URL, parámetros de QueryString, cuerpo, etc., todos se consideran parámetros para RestSharp, todos los que aparecen en la colección de parámetros de la solicitud, con su tipo correspondiente.
  • El método de registro debe llamarse DESPUÉS de que se realizó la solicitud. Esto es necesario debido a la forma en que funciona RestSharp, el método Execute agregará encabezados, ejecutará los autenticadores (si hay alguno configurado), etc. y todos estos modificarán la solicitud. Entonces, para tener todos los parámetros reales enviados registrados, el método Execute debería haberse llamado antes de registrar la solicitud.
  • RestSharp en sí nunca arrojará (en su lugar se guardan los errores en la propiedad response.ErrorException), pero creo que la deserialización podría arrojar (no estoy seguro) y además necesitaba registrar la respuesta en bruto, así que opté por implementar mi propia deserialización.
  • Tenga en cuenta que RestSharp usa su propio formato al convertir valores de parámetros para generar el Uri, por lo que la serialización de los parámetros para registrarlos puede no mostrar exactamente las mismas cosas que se pusieron en el Uri. Es por eso que el método IRestClient.BuildUri es muy bueno para obtener el realmente llamado Uri (incluyendo la url base, los segmentos url reemplazados, los parámetros queryString agregados, etc.).
  • EDITAR: También tenga en cuenta que podría suceder que el serializador que RestSharp está utilizando para el cuerpo no es el mismo que este código está usando, así que supongo que el código podría ajustarse para usar request.JsonSerializer.Serialize() para representar el parámetro body ( No he intentado esto).
  • Se necesitaba un código personalizado para lograr descripciones agradables en los registros de los valores de las enumeraciones.
  • StopWatch uso de StopWatch podría moverse para incluir la deserialización en la medición.

Aquí se trata de un ejemplo básico completo de clase base con registro (usando NLog):

using System; using System.Diagnostics; using System.Linq; using NLog; using Newtonsoft.Json; using RestSharp; namespace Apis { public abstract class RestApiBase { protected readonly IRestClient _restClient; protected readonly ILogger _logger; protected RestApiBase(IRestClient restClient, ILogger logger) { _restClient = restClient; _logger = logger; } protected virtual IRestResponse Execute(IRestRequest request) { IRestResponse response = null; var stopWatch = new Stopwatch(); try { stopWatch.Start(); response = _restClient.Execute(request); stopWatch.Stop(); // CUSTOM CODE: Do more stuff here if you need to... return response; } catch (Exception e) { // Handle exceptions in your CUSTOM CODE (restSharp will never throw itself) } finally { LogRequest(request, response, stopWatch.ElapsedMilliseconds); } return null; } protected virtual T Execute<T>(IRestRequest request) where T : new() { IRestResponse response = null; var stopWatch = new Stopwatch(); try { stopWatch.Start(); response = _restClient.Execute(request); stopWatch.Stop(); // CUSTOM CODE: Do more stuff here if you need to... // We can''t use RestSharp deserialization because it could throw, and we need a clean response // We need to implement our own deserialization. var returnType = JsonConvert.DeserializeObject<T>(response.Content); return returnType; } catch (Exception e) { // Handle exceptions in your CUSTOM CODE (restSharp will never throw itself) // Handle exceptions in deserialization } finally { LogRequest(request, response, stopWatch.ElapsedMilliseconds); } return default(T); } private void LogRequest(IRestRequest request, IRestResponse response, long durationMs) { _logger.Trace(() => { var requestToLog = new { resource = request.Resource, // Parameters are custom anonymous objects in order to have the parameter type as a nice string // otherwise it will just show the enum value parameters = request.Parameters.Select(parameter => new { name = parameter.Name, value = parameter.Value, type = parameter.Type.ToString() }), // ToString() here to have the method as a nice string otherwise it will just show the enum value method = request.Method.ToString(), // This will generate the actual Uri used in the request uri = _restClient.BuildUri(request), }; var responseToLog = new { statusCode = response.StatusCode, content = response.Content, headers = response.Headers, // The Uri that actually responded (could be different from the requestUri if a redirection occurred) responseUri = response.ResponseUri, errorMessage = response.ErrorMessage, }; return string.Format("Request completed in {0} ms, Request: {1}, Response: {2}", durationMs, JsonConvert.SerializeObject(requestToLog), JsonConvert.SerializeObject(responseToLog)); }); } } }

Esta clase registrará algo como esto (bonito formateado para pegar aquí):

Request completed in 372 ms, Request : { "resource" : "/Event/Create/{hostId}/{startTime}", "parameters" : [{ "name" : "hostId", "value" : "116644", "type" : "UrlSegment" }, { "name" : "startTime", "value" : "2016-05-18T19:48:58.9744911Z", "type" : "UrlSegment" }, { "name" : "application/json", "value" : "{/"durationMinutes/":720,/"seats/":100,/"title/":/"Hello !/"}", "type" : "RequestBody" }, { "name" : "api_key", "value" : "123456", "type" : "QueryString" }, { "name" : "Accept", "value" : "application/json, application/xml, text/json, text/x-json, text/javascript, text/xml", "type" : "HttpHeader" } ], "method" : "POST", "uri" : "http://127.0.0.1:8000/Event/Create/116644/2016-05-18T19%3A48%3A58.9744911Z?api_key=123456" }, Response : { "statusCode" : 200, "content" : "{/"eventId/":2000045,/"hostId/":116644,/"scheduledLength/":720,/"seatsReserved/":100,/"startTime/":/"2016-05-18T19:48:58.973Z/"", "headers" : [{ "Name" : "Access-Control-Allow-Origin", "Value" : "*", "Type" : 3 }, { "Name" : "Access-Control-Allow-Methods", "Value" : "POST, GET, OPTIONS, PUT, DELETE, HEAD", "Type" : 3 }, { "Name" : "Access-Control-Allow-Headers", "Value" : "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept", "Type" : 3 }, { "Name" : "Access-Control-Max-Age", "Value" : "1728000", "Type" : 3 }, { "Name" : "Content-Length", "Value" : "1001", "Type" : 3 }, { "Name" : "Content-Type", "Value" : "application/json", "Type" : 3 }, { "Name" : "Date", "Value" : "Wed, 18 May 2016 17:44:16 GMT", "Type" : 3 } ], "responseUri" : "http://127.0.0.1:8000/Event/Create/116644/2016-05-18T19%3A48%3A58.9744911Z?api_key=123456", "errorMessage" : null }

¡Espero que encuentres esto útil!


Puede usar Fiddler para capturar solicitudes HTTP.


Puedes intentar usar

Trace.WriteLine(request.JsonSerializer.Serialize(request));

para obtener una solicitud y

response.Content(); // as Luo have suggested

la solicitud no es la misma, como muestra Fiddler, pero contiene todos los datos y es legible (con algo de basura RestSharp al final).


Tienes que recorrer la request.Parameters . Los request.Parameters enumeran y formatean en una cadena en el formato que prefieras.

var sb = new StringBuilder(); foreach(var param in request.Parameters) { sb.AppendFormat("{0}: {1}/r/n", param.Name, param.Value); } return sb.ToString();

Si desea que la salida muestre encabezados de solicitud y luego el cuerpo similar a Fiddler, solo necesita ordenar los encabezados de Recopilación por solicitud y luego por Cuerpo de solicitud. El objeto Parameter en la colección tiene un parámetro Type enum.