C# unsupported grant type lors de l'appel à l'api web
j'essaie d'effectuer un Post à mon WebAPI à partir d'une application de bureau c# WPF.
peu importe ce que je fais, je reçois
{"error":" unsupported_grant_type"}
C'est ce que j'ai essayé (et j'ai essayé tout ce que j'ai pu trouver):
également dev api web actuellement actif pour les tests: http://studiodev.biz /
client http de base objet:
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("*/*"));
avec les méthodes d'envoi suivantes:
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");
après cet échec, j'ai cherché sur Google et j'ai essayé:
LoginModel data = new LoginModel(username, password);
string json = JsonConvert.SerializeObject(data);
await client.PostAsync("token", new JsonContent(json));
même résultat, donc j'ai essayé:
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(); }));
});
Note: je peux faire un appel réussi avec Chrome.
Mise À Jour Fiddler Résultat
pourrait quelqu'un s'il vous plaît m'aider à faire un appel réussi à l'api Web ci-dessus... S'il vous plaît, faites-moi savoir si je peux aider à clarifier. Merci!!
4 réponses
l'implémentation par défaut de OAuthAuthorizationServerHandler
n'accepte que le form encoding (i.e. application/x-www-form-urlencoded
) et non le JSON encoding ( application/JSON
).
votre demande ContentType
doit être application/x-www-form-urlencoded
et passer les données dans le corps comme:
grant_type=password&username=Alice&password=password123
c'est à dire pas au format JSON .
l'exemple de chrome ci-dessus fonctionne parce qu'il ne passe pas de données comme JSON. Vous avez seulement besoin de ceci pour obtenir un jeton; pour autres méthodes de votre API, vous pouvez utiliser JSON.
ce genre de problème est également discuté ici .
1) notez L'URL: "localhost:55828/token" (pas "localhost:55828/API/token")
2) noter les données de la demande. Ce n'est pas dans le format json, ce sont juste des données simples sans guillemets. "userName=xxx@gmail.com&password=Test123$&grant_type=" mot de passe
3) noter le type de contenu. Content-Type: 'application / x-www-form-urlencoded' (not Content-Type: 'application/json')
4) lorsque vous utilisez javascript pour faire une demande post, vous pouvez utiliser la mention suivante:
$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) {//...
voir les captures d'écran ci-dessous de Postman:
voici un exemple de travail que j'ai utilisé pour faire cette requête de mon application API Web locale tournant sur le port 43305 en utilisant SSL. J'ai mis le projet sur GitHub. 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; }
}
}
}
si vous utilisez RestSharp, vous devez faire la demande comme ceci:
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;
}