Tipo de concessão não suportado em c # ao chamar web api

Eu estou tentando executar um post para o meu WebAPI de um aplicativo de desktop AC # WPF.

Não importa o que eu faça, eu fico

{“error”: “unsupported_grant_type”}

Isso é o que eu tentei (e já tentei de tudo que pude encontrar):

Também dev API api atualmente ativa para testes: http://studiodev.biz/

object base do 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("*/*")); 

com os seguintes methods de envio:

 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"); 

Depois disso, eu fiz algumas pesquisas e tentei:

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

mesmo resultado, então eu tentei:

 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: posso efetuar uma chamada bem sucedida com o Chrome.

Atualizar o resultado do violinista

insira a descrição da imagem aqui

Alguém poderia me ajudar a fazer uma chamada bem sucedida para a API da web acima … Por favor, deixe-me saber se eu posso ajudar a esclarecer. Obrigado!!

A implementação padrão do OAuthAuthorizationServerHandler só aceita a codificação de formulário (ou seja, application/x-www-form-urlencoded ) e não a codificação JSON ( application/JSON ).

O ContentType da sua solicitação deve ser application/x-www-form-urlencoded e passar os dados no corpo como:

 grant_type=password&username=Alice&password=password123 

ou seja, não no formato JSON .

O exemplo de cromo acima funciona porque não está transmitindo dados como JSON. Você só precisa disso para obter um token; para outros methods da sua API, você pode usar o JSON.

Esse tipo de problema também é discutido aqui .

1) Observe a URL: “localhost: 55828 / token” (não “localhost: 55828 / API / token”)

2) Anote os dados da solicitação. Não está no formato json, apenas dados simples sem aspas duplas. “userName=xxx@gmail.com&password=Test123$&grant_type=password”

3) Observe o tipo de conteúdo. Tipo de Conteúdo: ‘application / x-www-form-urlencoded’ (não Tipo de Conteúdo: ‘application / json’)

4) Quando você usa o javascript para fazer o pedido, você pode usar o seguinte:

 $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) {//... 

Veja as capturas de canvas abaixo do Postman:

Pedido de carteiro

Cabeçalho de Solicitação de Carteiro

Aqui está um exemplo de trabalho que usei para fazer essa solicitação do meu aplicativo de API da Web local em execução na porta 43305 usando SSL. Eu coloquei o projeto no GitHub também. 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(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; } } } } 

Se você estiver usando RestSharp, você precisa fazer o pedido como este:

 public static U PostLogin(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(request); return response.Data; }