C#调用web api时不支持的授权类型

C#调用web api时不支持的授权类型,c#,wpf,asp.net-web-api,httpclient,token,C#,Wpf,Asp.net Web Api,Httpclient,Token,我正试图从一个c#WPF桌面应用程序向我的WebAPI发送帖子 不管我做什么,我都会 {“错误”:“不支持的授权类型”} 这就是我尝试过的(我尝试了我能找到的一切): 另外,开发web api当前正在进行测试: 基本http客户端对象: var client = new HttpClient() client.BaseAddress = new Uri("http://studiodev.biz/"); client.DefaultRequestHeaders.Accept.Clear(); c

我正试图从一个c#WPF桌面应用程序向我的WebAPI发送帖子

不管我做什么,我都会

{“错误”:“不支持的授权类型”}

这就是我尝试过的(我尝试了我能找到的一切):

另外,开发web api当前正在进行测试:

基本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("*/*"));
使用以下发送方法:

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");
失败后,我在谷歌上搜索了一下,并尝试:

LoginModel data = new LoginModel(username, password);
string json = JsonConvert.SerializeObject(data);
await client.PostAsync("token", new JsonContent(json));
同样的结果,所以我尝试:

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(); }));
});
注意:我可以使用Chrome成功拨打电话

更新Fiddler结果

有人能帮我成功调用上面的web api吗。。。 请让我知道,如果我可以帮助澄清。
谢谢

OAuthAuthorizationServerHandler的默认实现只接受表单编码(即
application/x-www-form-urlencoded
),而不接受JSON编码(
application/JSON

您的请求的
ContentType
应该是
application/x-www-form-urlencoded
,并在正文中传递数据,如下所示:

grant_type=password&username=Alice&password=password123
i、 e.不是JSON格式的

上面的chrome示例之所以有效,是因为它不以JSON的形式传递数据。你只需要这个来获得代币;对于API的其他方法,可以使用JSON


还讨论了这类问题。

这里是一个工作示例,我使用SSL向运行在端口43305上的本地Web API应用程序发出此请求。我也把这个项目放到了GitHub上。

使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用Newtonsoft.Json;
使用System.Net.Http;
使用System.Web;
命名空间GetAccessTokenSample
{
班级计划
{
专用静态字符串baseUrl=”https://localhost:44305";
静态void Main(字符串[]参数)
{
Console.WriteLine(“输入用户名:”);
字符串username=Console.ReadLine();
Console.WriteLine(“输入密码:”);
字符串密码=Console.ReadLine();
LoginTokenResult accessToken=GetLoginToken(用户名、密码);
if(accessToken.accessToken!=null)
{
Console.WriteLine(accessToken);
}
其他的
{
WriteLine(“发生错误:{0},{1}”,accessToken.Error,accessToken.ErrorDescription);
}
}
私有静态LoginTokenResult GetLoginToken(字符串用户名、字符串密码)
{
HttpClient=新的HttpClient();
client.BaseAddress=新Uri(baseUrl);
//TokenRequestViewModel tokenRequest=新的TokenRequestViewModel(){
//password=userInfo.password,username=userInfo.username};
HttpResponseMessage响应=
client.PostAsync(“令牌”,
新的StringContent(string.Format(“grant_type=password&username={0}&password={1}”),
HttpUtility.UrlEncode(用户名),
HttpUtility.UrlEncode(密码)),Encoding.UTF8,
“application/x-www-form-urlencoded”)。结果;
字符串resultJSON=response.Content.ReadAsStringAsync().Result;
LoginTokenResult=JsonConvert.DeserializeObject(resultJSON);
返回结果;
}
公共类LoginTokenResult
{
公共重写字符串ToString()
{
返回AccessToken;
}
[JsonProperty(PropertyName=“访问令牌”)]
公共字符串AccessToken{get;set;}
[JsonProperty(PropertyName=“error”)]
公共字符串错误{get;set;}
[JsonProperty(PropertyName=“error\u description”)]
公共字符串ErrorDescription{get;set;}
}
}
}

如果您使用的是RestSharp,则需要像这样发出请求:

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;

        }
publicstaticu-PostLogin(字符串url,身份验证对象)
其中U:new()
{
RestClient=newrestclient();
client.BaseUrl=新Uri(主机+url);
var请求=新的重新请求(Method.POST);
string encodedBody=string.Format(“grant_type=password&username={0}&password={1}”,
对象用户名、对象密码);
request.AddParameter(“application/x-www-form-urlencoded”,encodedBody,ParameterType.RequestBody);
request.AddParameter(“内容类型”,“应用程序/x-www-form-urlencoded”,ParameterType.HttpHeader);
var response=client.Execute(请求);
返回响应数据;
}
1)注意URL:“localhost:55828/token”(而不是“localhost:55828/API/token”)

2) 注意请求数据。它不是json格式,只是没有双引号的普通数据。 “用户名=xxx@gmail.com&password=Test123$&grant\u type=password”

3) 请注意内容类型。内容类型:“application/x-www-form-urlencoded”(不是内容类型:“application/json”)

4) 当您使用javascript发出post请求时,可以使用以下命令:

$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) {//...
请参见以下邮差截图:


也有同样的问题,但仅通过令牌URL的安全HTTP解决了我的问题。请参阅示例httpclient代码。普通HTTP在服务器维护后停止工作

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;
var-apirl=”https://appdomain.com/token"
var client=新的HttpClient();
client.Timeout=newtimespan(1,0,0);
var loginda=新字典
{
{“UserName”,model.UserName},
{“Password”,model.Password},
{“授权类型”,“密码”}
};
var内容=新的FormUrlEncodedContent(loginData);
var response=client.PostAsync(apirl,content.Result);

在我的情况下,我忘记了安装包Token.JWT,所以您也需要在项目中安装。
安装软件包System.IdentityModel.Tokens.Jwt-版本6.7.1

这可能是协议失败的原因 它是必需的://


例:https://localhost:port/oauth/token

您是否尝试过使用Fiddler来确定来自Chrome的呼叫与来自WPF应用程序的呼叫之间的差异?我尝试过,请原谅
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;