C'est le code que j'ai jusqu'à présent:
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);
}
}
}
}
Le problème est que je pense que le bloc d'exception est en cours de déclenchement (car lorsque je supprime le test try-catch, je reçois un message d'erreur de serveur (500). Mais je ne vois pas les lignes Console.Out que j'ai insérées dans le catch.
Ma console:
The thread 'vshost.NotifyLoad' (0x1a20) has exited with code 0 (0x0).
The thread '<No Name>' (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. preston 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 '<No Name>' (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).
J'utilise Visual Studio 2011 Beta et .NET 4.5 Beta.
L'API Web ASP.Net a remplacé l'API Web WCF mentionnée précédemment.
Je pensais publier une réponse mise à jour car la plupart de ces réponses datent du début de 2012, et ce fil est l’un des meilleurs résultats lors de la recherche sur Google de "call reposful service c #".
Microsoft recommande actuellement d'utiliser les bibliothèques clientes de l'API Web Microsoft ASP.NET pour utiliser un service RESTful. Ceci est disponible sous forme de package NuGet, Microsoft.AspNet.WebApi.Client. Vous devrez ajouter ce package NuGet à votre solution.
Voici à quoi ressemblerait votre exemple une fois implémenté à l'aide de la bibliothèque client 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<IEnumerable<DataObject>>().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 vous envisagez de faire plusieurs demandes, vous devez réutiliser votre instance HttpClient. Voir cette question et ses réponses pour plus de détails sur la raison pour laquelle une instruction using n'a pas été utilisée sur l'instance HttpClient dans ce cas: Les attributs HttpClient et HttpClientHandler doivent-ils être supprimés?
Pour plus de détails, y compris d'autres exemples, allez ici: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client
Cet article de blog peut également être utile: http://johnnycode.com/2012/02/23/consuming-your-own-asp-net-web-api-rest-service/
Ma suggestion serait d'utiliser RestSharp . Vous pouvez appeler des services REST et les convertir en objets POCO avec très peu de code passe-partout pour pouvoir analyser la réponse. Cela ne résoudra pas votre erreur particulière, mais répondra à votre question générale sur la manière de passer des appels vers les services REST. Devoir changer votre code pour l'utiliser devrait porter ses fruits en termes de facilité d'utilisation et de robustesse. C'est juste mes 2 centimes si
Sans lien, j'en suis sûr, mais enveloppez vos objets IDisposable
dans des blocs using
pour garantir une élimination appropriée:
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() ?? Stream.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);
}
}
}
}
Veuillez utiliser le code ci-dessous pour votre demande d’API 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;
}
}
}
}
Update pour appeler une API REST lors de l'utilisation de .NET 4.5 ou .NET Core
Je suggérerais DalSoft.RestClient (mais je l’ai créé). La raison étant qu’il utilise le typage dynamique, vous pouvez tout regrouper dans un seul appel courant, y compris la sérialisation/dé-sérialisation. Vous trouverez ci-dessous un exemple de travail PUT:
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);
Consultez Refit pour passer des appels vers des services de repos à partir de .net. Je l’ai trouvé très facile à utiliser: https://github.com/paulcbetts/refit
Refit: La bibliothèque REST automatique, sécurisée pour le texte, pour .NET Core, Xamarin et .NET
Refit est une bibliothèque fortement inspirée de la bibliothèque de rénovation de Square, et cela transforme votre API REST en une interface dynamique:
public interface IGitHubApi {
[Get("/users/{user}")]
Task<User> GetUser(string user); } The RestService class generates an implementation of IGitHubApi that uses HttpClient to make its calls:
var gitHubApi = RestService.For<IGitHubApi>("https://api.github.com");
var octocat = await gitHubApi.GetUser("octocat");
// 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;
}
// 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;
}
}
Remarque: Pour sérialiser et désirialze JSON, j'ai utilisé le package Newtonsoft.Json NuGet.
Voici différentes manières d'appeler une API externe en C # (mise à jour en 2019).
. Les méthodes intégrées de .NET:
Les packages NuGet gratuits (open-source) , qui offrent franchement une expérience de développeur bien meilleure que celle des clients intégrés à .NET:
Tous les packages ci-dessus offrent une excellente expérience de développement (c.-à-d. Une API simple et concise) et sont bien entretenus.
(*) en août 2019
Exemple: Obtention d'un élément Todo à partir d'une API Fake Rest à l'aide de ServiceStack.Text. Les autres bibliothèques ont une syntaxe très similaire.
class Program
{
static void Main(string[] args)
{
// fake rest API
string url = "https://jsonplaceholder.typicode.com/todos/1";
// GET data from api & map to Poco
var todo = url.GetJsonFromUrl().FromJson<Todo>();
// print result to screen
todo.PrintDump();
}
public class Todo
{
public int UserId { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public bool Completed { get; set; }
}
}
L'exécution de l'exemple ci-dessus dans une application .NET Core Console génère le résultat suivant.
Installez ces paquets en utilisant NuGet
Install-Package ServiceStack.Text, or
Install-Package RestSharp, or
Install-Package Flurl.Http
Ceci est un exemple de code qui fonctionne à coup sûr. Il m'a fallu une journée pour lire ceci afin de lire un ensemble d'objets du service Rest:
RootObject est le type de l'objet Im en train de lire le service rest.
string url = @"http://restcountries.eu/rest/v1";
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(IEnumerable<RootObject>));
WebClient syncClient = new WebClient();
string content = syncClient.DownloadString(url);
using (MemoryStream memo = new MemoryStream(Encoding.Unicode.GetBytes(content)))
{
IEnumerable<RootObject> countries = (IEnumerable<RootObject>)serializer.ReadObject(memo);
}
Console.Read();
J'aimerais partager ma solution dans ASP.NET Core
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
namespace WebApp
{
public static class HttpHelper
{
// In my case this is https://localhost:44366/
private static readonly string apiBasicUri = ConfigurationManager.AppSettings["apiBasicUri"];
public static async Task Post<T>(string url, T contentValue)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var content = new StringContent(JsonConvert.SerializeObject(contentValue), Encoding.UTF8, "application/json");
var result = await client.PostAsync(url, content);
result.EnsureSuccessStatusCode();
}
}
public static async Task Put<T>(string url, T stringValue)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var content = new StringContent(JsonConvert.SerializeObject(stringValue), Encoding.UTF8, "application/json");
var result = await client.PutAsync(url, content);
result.EnsureSuccessStatusCode();
}
}
public static async Task<T> Get<T>(string url)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var result = await client.GetAsync(url);
result.EnsureSuccessStatusCode();
string resultContentString = await result.Content.ReadAsStringAsync();
T resultContent = JsonConvert.DeserializeObject<T>(resultContentString);
return resultContent;
}
}
public static async Task Delete(string url)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var result = await client.DeleteAsync(url);
result.EnsureSuccessStatusCode();
}
}
}
}
Pour poster, utilisez quelque chose comme ceci:
await HttpHelper.Post<Setting>($"/api/values/{id}", setting);
Exemple de suppression:
await HttpHelper.Delete($"/api/values/{id}");
Exemple pour obtenir la liste:
List<ClaimTerm> claimTerms = await HttpHelper.Get<List<ClaimTerm>>("/api/values/");
Exemple pour obtenir un seul:
ClaimTerm processedClaimImage = await HttpHelper.Get<ClaimTerm>($"/api/values/{id}");
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=@"<root><childnodes>passing parameters</childnodes></root>";
string xmlroot2=@"<root><childnodes>passing parameters</childnodes></root>";
//---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();
Je l'ai fait de cette manière simple, avec Web Api 2.0 . Vous pouvez supprimer UseDefaultCredentials.Je l'ai utilisé pour mes propres cas d'utilisation.
List<YourObject> listObjects = new List<YourObject>();
string response = "";
using (var client = new WebClient() { UseDefaultCredentials = true })
{
response = client.DownloadString(apiUrl);
}
listObjects = JsonConvert.DeserializeObject<List<YourObject>>(response);
return listObjects ;
Puisque vous utilisez Visual Studio 11 Beta, vous souhaiterez utiliser les versions les plus récentes et les meilleures. La nouvelle Web Api contient des classes pour cela.
Voir HttpClient: http://wcf.codeplex.com/wikipage?title=WCF%20HTTP