¿Cómo hago llamadas a una API REST usando c #?

Este es el código que tengo hasta ahora:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System; using System.Net.Http; using System.Web; using System.Net; using System.IO; namespace ConsoleProgram { public class Class1 { private const string URL = "https://sub.domain.com/objects.json?api_key=123"; private const string DATA = @"{""object"":{""name"":""Name""}}"; static void Main(string[] args) { Class1.CreateObject(); } private static void CreateObject() { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); request.Method = "POST"; request.ContentType = "application/json"; request.ContentLength = DATA.Length; StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII); requestWriter.Write(DATA); requestWriter.Close(); try { WebResponse webResponse = request.GetResponse(); Stream webStream = webResponse.GetResponseStream(); StreamReader responseReader = new StreamReader(webStream); string response = responseReader.ReadToEnd(); Console.Out.WriteLine(response); responseReader.Close(); } catch (Exception e) { Console.Out.WriteLine("-----------------"); Console.Out.WriteLine(e.Message); } } } } 

El problema es que creo que se está activando el bloque de excepción (porque cuando elimino el try-catch, recibo un mensaje de error del servidor (500). Pero no veo la consola. Salgo de las líneas que pongo en el bloque catch.

Mi consola:

 The thread 'vshost.NotifyLoad' (0x1a20) has exited with code 0 (0x0). The thread '' (0x1988) has exited with code 0 (0x0). The thread 'vshost.LoadReference' (0x1710) has exited with code 0 (0x0). 'ConsoleApplication1.vshost.exe' (Managed (v4.0.30319)): Loaded 'c:\users\l. prestn sego iii\documents\visual studio 11\Projects\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe', Symbols loaded. 'ConsoleApplication1.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. A first chance exception of type 'System.Net.WebException' occurred in System.dll The thread 'vshost.RunParkingWindow' (0x184c) has exited with code 0 (0x0). The thread '' (0x1810) has exited with code 0 (0x0). The program '[2780] ConsoleApplication1.vshost.exe: Program Trace' has exited with code 0 (0x0). The program '[2780] ConsoleApplication1.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0). 

Estoy usando Visual Studio 2011 Beta y .NET 4.5 Beta.

La API web de ASP.Net ha reemplazado la API web de WCF mencionada anteriormente.

Pensé en publicar una respuesta actualizada ya que la mayoría de estas respuestas son de principios de 2012, y este hilo es uno de los principales resultados al hacer una búsqueda en Google de “call restful service c #”.

La orientación actual de Microsoft es utilizar las bibliotecas de cliente de API web Microsoft ASP.NET para consumir un servicio RESTful. Esto está disponible como un paquete NuGet, Microsoft.AspNet.WebApi.Client. Deberá agregar este paquete NuGet a su solución.

Así es como se vería su ejemplo cuando se implementa con la biblioteca de cliente de ASP.Net Web API:

 using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; namespace ConsoleProgram { public class DataObject { public string Name { get; set; } } public class Class1 { private const string URL = "https://sub.domain.com/objects.json"; private string urlParameters = "?api_key=123"; static void Main(string[] args) { HttpClient client = new HttpClient(); client.BaseAddress = new Uri(URL); // Add an Accept header for JSON format. client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); // List data response. HttpResponseMessage response = client.GetAsync(urlParameters).Result; // Blocking call! Program will wait here until a response is received or a timeout occurs. if (response.IsSuccessStatusCode) { // Parse the response body. var dataObjects = response.Content.ReadAsAsync>().Result; //Make sure to add a reference to System.Net.Http.Formatting.dll foreach (var d in dataObjects) { Console.WriteLine("{0}", d.Name); } } else { Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase); } //Make any other calls using HttpClient here. //Dispose once all HttpClient calls are complete. This is not necessary if the containing object will be disposed of; for example in this case the HttpClient instance will be disposed automatically when the application terminates so the following call is superfluous. client.Dispose(); } } } 

Si planea realizar varias solicitudes, debe volver a utilizar su instancia de HttpClient. Consulte esta pregunta y sus respuestas para obtener más detalles sobre por qué no se utilizó una statement de uso en la instancia de HttpClient en este caso: ¿Hay que eliminar HttpClient y HttpClientHandler?

Para obtener más detalles, incluidos otros ejemplos, vaya aquí: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-f-a-net-client

Esta publicación de blog también puede ser útil: http://johnnycode.com/2012/02/23/consuming-your-own-asp-net-web-api-rest-service/

Mi sugerencia sería usar RestSharp . Puede hacer llamadas a los servicios REST y hacer que estos se conviertan en objetos POCO con muy poco código repetitivo para que realmente tengan que analizarse a través de la respuesta. Esto no resolverá su error particular, pero responde su pregunta general sobre cómo hacer llamadas a los servicios REST. Tener que cambiar el código para usarlo debería dar resultado en la facilidad de uso y la solidez para seguir adelante. Eso es solo mi 2 centavos aunque

Sin relación, estoy seguro, pero envuelva sus objetos IDisposable en el using bloques para garantizar la eliminación adecuada:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System; using System.Web; using System.Net; using System.IO; namespace ConsoleProgram { public class Class1 { private const string URL = "https://sub.domain.com/objects.json?api_key=123"; private const string DATA = @"{""object"":{""name"":""Name""}}"; static void Main(string[] args) { Class1.CreateObject(); } private static void CreateObject() { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); request.Method = "POST"; request.ContentType = "application/json"; request.ContentLength = DATA.Length; using (Stream webStream = request.GetRequestStream()) using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII)) { requestWriter.Write(DATA); } try { WebResponse webResponse = request.GetResponse(); using (Stream webStream = webResponse.GetResponseStream()) { if (webStream != null) { using (StreamReader responseReader = new StreamReader(webStream)) { string response = responseReader.ReadToEnd(); Console.Out.WriteLine(response); } } } } catch (Exception e) { Console.Out.WriteLine("-----------------"); Console.Out.WriteLine(e.Message); } } } } 

Utilice el siguiente código para su solicitud de API de REST

 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Json; namespace ConsoleApplication2 { class Program { private const string URL = "https://XXXX/rest/api/2/component"; private const string DATA = @"{ ""name"": ""Component 2"", ""description"": ""This is a JIRA component"", ""leadUserName"": ""xx"", ""assigneeType"": ""PROJECT_LEAD"", ""isAssigneeTypeValid"": false, ""project"": ""TP""}"; static void Main(string[] args) { AddComponent(); } private static void AddComponent() { System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(); client.BaseAddress = new System.Uri(URL); byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password"); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred)); client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); System.Net.Http.HttpContent content = new StringContent(DATA, UTF8Encoding.UTF8, "application/json"); HttpResponseMessage messge = client.PostAsync(URL, content).Result; string description = string.Empty; if (messge.IsSuccessStatusCode) { string result = messge.Content.ReadAsStringAsync().Result; description = result; } } } } 

Actualización para llamar a una API REST cuando se usa .NET 4.5.

Sugeriría DalSoft.RestClient (advertencia que lo creé). El motivo es que utiliza el tipado dynamic y puede resumir todo en una sola llamada fluida, incluida la serialización / deserialización. Debajo hay un ejemplo de PUT que funciona:

 dynamic client = new RestClient("http://jsonplaceholder.typicode.com"); var post = new Post { title = "foo", body = "bar", userId = 10 }; var result = await client.Posts(1).Put(post); 

Consulte Refit para realizar llamadas a servicios de descanso desde .net. Lo encontré muy fácil de usar: https://github.com/paulcbetts/refit

Reposición: la biblioteca REST automática de tipo seguro para .NET Core, Xamarin y .NET

Refit es una biblioteca fuertemente inspirada en la biblioteca de Retrofit de Square, y convierte su API REST en una interfaz en vivo:

 public interface IGitHubApi { [Get("/users/{user}")] Task GetUser(string user); } The RestService class generates an implementation of IGitHubApi that uses HttpClient to make its calls: var gitHubApi = RestService.For("https://api.github.com"); var octocat = await gitHubApi.GetUser("octocat"); 
  var TakingRequset = WebRequest.Create("http://xxx.acv.com/MethodName/Get"); TakingRequset.Method = "POST"; TakingRequset.ContentType = "text/xml;charset=utf-8"; TakingRequset.PreAuthenticate = true; //---Serving Request path query var PAQ = TakingRequset.RequestUri.PathAndQuery; //---creating your xml as per the host reqirement string xmlroot=@"passing parameters"; string xmlroot2=@"passing parameters"; //---Adding Headers as requested by host xmlroot2 = (xmlroot2 + "XXX---"); //---Adding Headers Value as requested by host // var RequestheaderVales = Method(xmlroot2); WebProxy proxy = new WebProxy("XXXXX-----llll", 8080); proxy.Credentials = new NetworkCredential("XXX---uuuu", "XXX----", "XXXX----"); System.Net.WebRequest.DefaultWebProxy = proxy; // Adding The Request into Headers TakingRequset.Headers.Add("xxx", "Any Request Variable "); TakingRequset.Headers.Add("xxx", "Any Request Variable"); byte[] byteData = Encoding.UTF8.GetBytes(xmlroot); TakingRequset.ContentLength = byteData.Length; using (Stream postStream = TakingRequset.GetRequestStream()) { postStream.Write(byteData, 0, byteData.Length); postStream.Close(); } StreamReader stredr = new StreamReader(TakingRequset.GetResponse().GetResponseStream()); string response = stredr.ReadToEnd(); 

Este es un código de ejemplo que funciona con seguridad. Me tomó un día hacer esto para leer un conjunto de objetos del servicio Rest:

RootObject es el tipo de objeto que estoy leyendo desde el servicio de descanso.

 string url = @"http://restcountries.eu/rest/v1"; DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(IEnumerable)); WebClient syncClient = new WebClient(); string content = syncClient.DownloadString(url); using (MemoryStream memo = new MemoryStream(Encoding.Unicode.GetBytes(content))) { IEnumerable countries = (IEnumerable)serializer.ReadObject(memo); } Console.Read(); 

Como está utilizando Visual Studio 11 Beta, querrá usar lo último y lo mejor. El nuevo API web contiene clases para esto.

Ver HttpClient: http://wcf.codeplex.com/wikipage?title=WCF%20HTTP

OBTENER:

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

ENVIAR:

 // 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()) { // got response length = response.ContentLength; } } catch (WebException ex) { WebResponse errorResponse = ex.Response; using(Stream responseStream = errorResponse.GetResponseStream()) { StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); String errorText = reader.ReadToEnd(); // log errorText } throw; } } 

Nota: Para serializar y desirializar JSON utilicé el paquete Newtonsoft.Json NuGet.