tutorial net ejemplo consumir async asp c# wpf asp.net-web-api httpclient token

net - httpclient ejemplo c#



Tipo de concesiĆ³n C#no admitido al llamar a la API web (5)

Estoy tratando de realizar una publicación en mi WebAPI desde la aplicación de escritorio ac # WPF.

No importa lo que haga, me sale

{"error": "unsupported_grant_type"}

Esto es lo que he intentado (y he intentado todo lo que pude encontrar):

También dev web api actualmente activa para pruebas: http://studiodev.biz/

objeto base del cliente http:

var client = new HttpClient() client.BaseAddress = new Uri("http://studiodev.biz/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));

con los siguientes métodos de envío:

var response = await client.PostAsJsonAsync("token", "{''grant_type''=''password''&''username''=''username''&''password''=''password''"); var response = await client.PostAsJsonAsync("token", "grant_type=password&username=username&password=password");

Después de que eso falló, busqué en Google e intenté:

LoginModel data = new LoginModel(username, password); string json = JsonConvert.SerializeObject(data); await client.PostAsync("token", new JsonContent(json));

mismo resultado, así que probé:

req.Content = new StringContent(json, Encoding.UTF8, "application/x-www-form-urlencoded"); await client.SendAsync(req).ContinueWith(respTask => { Application.Current.Dispatcher.Invoke(new Action(() => { label.Content = respTask.Result.ToString(); })); });

Nota: puedo hacer una llamada exitosa con Chrome.

Actualizar el resultado del violinista

¿Podría alguien ayudarme a hacer una llamada exitosa a la API web anterior ... Avíseme si puedo ayudar a aclarar. ¡¡Gracias!!


1) Tenga en cuenta la URL: "localhost: 55828 / token" (no "localhost: 55828 / API / token")

2) Tenga en cuenta los datos de la solicitud. No está en formato json, solo son datos simples sin comillas dobles. "[email protected]&password=Test123$&grant_type=password"

3) Tenga en cuenta el tipo de contenido. Tipo de contenido: ''application / x-www-form-urlencoded'' (no Content-Type: ''application / json'')

4) Cuando usa javascript para hacer una solicitud de publicación, puede usar lo siguiente:

$http.post("localhost:55828/token", "userName=" + encodeURIComponent(email) + "&password=" + encodeURIComponent(password) + "&grant_type=password", {headers: { ''Content-Type'': ''application/x-www-form-urlencoded'' }} ).success(function (data) {//...

Vea las capturas de pantalla a continuación de Postman:


Aquí hay un ejemplo de trabajo que utilicé para hacer esta solicitud de mi aplicación API web local que se ejecuta en el puerto 43305 usando SSL. Puse el proyecto en GitHub también. https://github.com/casmer/WebAPI-getauthtoken

using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using System.Net.Http; using System.Web; namespace GetAccessTokenSample { class Program { private static string baseUrl = "https://localhost:44305"; static void Main(string[] args) { Console.WriteLine("Enter Username: "); string username= Console.ReadLine(); Console.WriteLine("Enter Password: "); string password = Console.ReadLine(); LoginTokenResult accessToken = GetLoginToken(username,password); if (accessToken.AccessToken != null) { Console.WriteLine(accessToken); } else { Console.WriteLine("Error Occurred:{0}, {1}", accessToken.Error, accessToken.ErrorDescription); } } private static LoginTokenResult GetLoginToken(string username, string password) { HttpClient client = new HttpClient(); client.BaseAddress = new Uri(baseUrl); //TokenRequestViewModel tokenRequest = new TokenRequestViewModel() { //password=userInfo.Password, username=userInfo.UserName}; HttpResponseMessage response = client.PostAsync("Token", new StringContent(string.Format("grant_type=password&username={0}&password={1}", HttpUtility.UrlEncode(username), HttpUtility.UrlEncode(password)), Encoding.UTF8, "application/x-www-form-urlencoded")).Result; string resultJSON = response.Content.ReadAsStringAsync().Result; LoginTokenResult result = JsonConvert.DeserializeObject<LoginTokenResult>(resultJSON); return result; } public class LoginTokenResult { public override string ToString() { return AccessToken; } [JsonProperty(PropertyName = "access_token")] public string AccessToken { get; set; } [JsonProperty(PropertyName = "error")] public string Error { get; set; } [JsonProperty(PropertyName = "error_description")] public string ErrorDescription { get; set; } } } }


La implementación predeterminada de OAuthAuthorizationServerHandler solo acepta codificación de formulario (es decir, application/x-www-form-urlencoded ) y no codificación JSON ( application/JSON ).

El ContentType su solicitud debe ser application/x-www-form-urlencoded y pasar los datos en el cuerpo como:

grant_type=password&username=Alice&password=password123

es decir, no en formato JSON .

El ejemplo de Chrome anterior funciona porque no está pasando datos como JSON. Solo necesitas esto para obtener un token; para otros métodos de tu API puedes usar JSON.

Este tipo de problema también se discute here .


Si está utilizando RestSharp, debe realizar la solicitud de esta manera:

public static U PostLogin<U>(string url, Authentication obj) where U : new() { RestClient client = new RestClient(); client.BaseUrl = new Uri(host + url); var request = new RestRequest(Method.POST); string encodedBody = string.Format("grant_type=password&username={0}&password={1}", obj.username,obj.password); request.AddParameter("application/x-www-form-urlencoded", encodedBody, ParameterType.RequestBody); request.AddParameter("Content-Type", "application/x-www-form-urlencoded", ParameterType.HttpHeader); var response = client.Execute<U>(request); return response.Data; }


Tuve los mismos problemas, pero solo resolvió el mío sobre HTTP seguro para la URL del token. Ver ejemplo de código httpclient. HTTP ordinario simplemente deja de funcionar después del mantenimiento del servidor

var apiUrl = "https://appdomain.com/token" var client = new HttpClient(); client.Timeout = new TimeSpan(1, 0, 0); var loginData = new Dictionary<string, string> { {"UserName", model.UserName}, {"Password", model.Password}, {"grant_type", "password"} }; var content = new FormUrlEncodedContent(loginData); var response = client.PostAsync(apiUrl, content).Result;