La mejor manera de llamar a un servicio web JSON desde una consola .NET

89

Estoy alojando un servicio web en ASP.Net MVC3 que devuelve una cadena Json. ¿Cuál es la mejor manera de llamar al servicio web desde la aplicación de consola ac # y analizar el retorno en un objeto .NET?

¿Debo hacer referencia a MVC3 en mi aplicación de consola?

Json.Net tiene algunos métodos agradables para serializar y deserializar objetos .NET, pero no veo que tenga formas de POSTAR y OBTENER valores desde un servicio web.

¿O debería crear mi propio método auxiliar para PUBLICAR y OBTENER en el servicio web? ¿Cómo serializaría mi objeto .net en pares clave-valor?

BrokeMyLegBici
fuente

Respuestas:

142

Utilizo HttpWebRequest para OBTENER del servicio web, que me devuelve una cadena JSON. Se parece a esto para un GET:

// Returns JSON string
string GET(string url) 
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    try {
        WebResponse response = request.GetResponse();
        using (Stream responseStream = response.GetResponseStream()) {
            StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8);
            return reader.ReadToEnd();
        }
    }
    catch (WebException ex) {
        WebResponse errorResponse = ex.Response;
        using (Stream responseStream = errorResponse.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.GetEncoding("utf-8"));
            String errorText = reader.ReadToEnd();
            // log errorText
        }
        throw;
    }
}

Luego uso JSON.Net para analizar dinámicamente la cadena. Alternativamente, puede generar la clase C # de forma estática a partir de la salida JSON de muestra utilizando esta herramienta de codeplex: http://jsonclassgenerator.codeplex.com/

POST se ve así:

// POST a JSON string
void POST(string url, string jsonContent) 
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "POST";

    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    Byte[] byteArray = encoding.GetBytes(jsonContent);

    request.ContentLength = byteArray.Length;
    request.ContentType = @"application/json";

    using (Stream dataStream = request.GetRequestStream()) {
        dataStream.Write(byteArray, 0, byteArray.Length);
    }
    long length = 0;
    try {
        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
            length = response.ContentLength;
        }
    }
    catch (WebException ex) {
        // Log exception and throw as for GET example above
    }
}

Utilizo un código como este en pruebas automatizadas de nuestro servicio web.

GarethOwen
fuente
JsonClassGenerator es increíble. La deserialización es fácil ya que simplemente construye el objeto fuertemente tipado pasando la cadena json.
AaronLS
Si tiene caracteres en el conjunto no ASCII, el código que tiene debe modificarse un poco. ContentLength representa el número de bytes en el contenido publicado, por lo que técnicamente request.ContentLength debe establecerse en byteArray.Length, no en jsonContent.Length.
Grady Werner
Encoding.GetEncoding("utf-8")puede ser reemplazado porEncoding.UTF8
JoelFan
Gracias, esto es muy útil
shweta
Como parte del token de autorización se establecerá, pero es posible que tengamos que pasar encabezados también si es necesario para probar. Como esta request.Method = "GET"; request.Timeout = 20000; request.ContentType = "aplicación / json"; request.Headers.Add ("Autorización", "Portador de su token:
Kurkula
51

WebClient para recuperar el contenido de la URL remota y JavaScriptSerializer o Json.NET para deserializar el JSON en un objeto .NET. Por ejemplo, define una clase de modelo que reflejará la estructura JSON y luego:

using (var client = new WebClient())
{
    var json = client.DownloadString("http://example.com/json");
    var serializer = new JavaScriptSerializer();
    SomeModel model = serializer.Deserialize<SomeModel>(json);
    // TODO: do something with the model
}

También hay algunos marcos de cliente REST que puede consultar, como RestSharp .

Darin Dimitrov
fuente
@BrokeMyLegBiking, ¿cuál? No tiene nada que ver con ASPAjax. Si está hablando de la clase JavaScriptSerializer, está integrada en .NET en el ensamblado System.Web.Extensions para que no tenga que descargar ni instalar nada.
Darin Dimitrov
¿Hay alguna manera de convertir todos los nombres de propiedad / valores de propiedad del objeto ac # en pares clave-valor POST (o pares clave-valor GET)? para poder usar efectivamente el objeto c # como un valor de entrada para mi método de servicio web?
BrokeMyLegBiking
@BrokeMyLegBiking, eso dependerá de qué objeto tenga y cómo espera el servicio web la entrada.
Darin Dimitrov
3
Realmente disfruté de la biblioteca RestSharp. Gracias por mencionar eso.
Bryan Ray
1
Daren, puedes actualizar esto, el client.downloadstring () ya no es viable.
JReam
9

Aunque las respuestas existentes son enfoques válidos, son anticuados. HttpClient es una interfaz moderna para trabajar con servicios web RESTful. Consulte la sección de ejemplos de la página en el enlace, tiene un caso de uso muy sencillo para un HTTP GET asincrónico.

using (var client = new System.Net.Http.HttpClient())
{
    return await client.GetStringAsync("https://reqres.in/api/users/3"); //uri
}
LostNomad311
fuente