通过 WebApi 返回 JSON
Returning JSON via WebApi
我正在使用 C# 中的 HttpClient 尝试将 SSO(单点登录)集成到我们的一些自定义应用程序中。
我已经在我们的 JavaScript 应用程序中成功地做到了这一点,但是我在将它集成到我们的一些 Umbraco 网站时遇到了一些困难。
到目前为止我的代码:
using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
using Newtonsoft.Json;
using System.Collections.Generic;
using Umbraco.Web;
using Umbraco.Web.WebApi;
namespace Umbraco.WebApi
{
public class TestController : UmbracoApiController
{
public HttpClient client = new HttpClient();
[HttpPost]
public async Task<Object> GetRefreshToken(Token t)
{
try {
string refToken = t.refresh_token;
var values = new Dictionary<string, string>
{
{ "grant_type", "refresh_token" },
{ "client_id", "CLIENTID" },
{ "client_secret", "CLIENTSECRET" },
{ "refresh_token", refToken }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://URL.org/Token", content);
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
} catch(HttpRequestException e) {
return e;
}
}
public class Token
{
public string refresh_token { get; set; }
}
public class AuthData
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_int { get; set; }
public string refresh_token { get; set; }
public string userName { get; set; }
public string client_id { get; set; }
public DateTime issued { get; set; }
public DateTime expires { get; set; }
}
}
}
它成功 return 我想要的数据,但 returned 数据存在问题(已删除敏感数据):
<z:anyType xmlns:d1p1="http://www.w3.org/2001/XMLSchema" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" i:type="d1p1:string">
{"access_token":"XXXXXXXX","token_type":"bearer","expires_in":1199,"refresh_token":"XXXXXX","userName":"XXXXXX","as:client_id":"XXXXX",".issued":"Fri, 20 Sep 2019 13:23:48 GMT",".expires":"Fri, 20 Sep 2019 13:43:48 GMT"}
</z:anyType>
它似乎也被 return 编辑为 XML 而不是 JSON?
C# 不是我最擅长的语言,所以我可能完全错了。
感谢任何帮助。
解决此问题的方法之一是通过添加正确的请求 headers
在您的响应中专门请求 json 格式
Accept: application/json
像这样尝试
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
现在,如果服务器关注请求 header,它将 return 返回给您 json。
它可能默认为 xml,因为在您的请求中没有这样的 header 或者服务器仅支持 returning xml 响应。
编辑:如果您无法让服务器到达 return json,您可以将 xml 字符串响应转换为 json 字符串。看看这个example。转换后,您可以从您的控制器正常 return 您的 json 字符串。
编辑:
好的,试试下面这个示例:
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("client_id", ""),
new KeyValuePair<string, string>("scope", ""),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("redirect_uri", ""),
new KeyValuePair<string, string>("code", ""),
new KeyValuePair<string, string>("client_secret","")
});
AADTokenResponse TokenResponse = null;
string _baseAddress = string.Format("https://yourTargetDomain.com/");
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = await client.PostAsync("targetApiSegment", content);
if (responseMessage.IsSuccessStatusCode)
{
var responseString = await responseMessage.Content.ReadAsStringAsync();
TokenResponse = JsonConvert.DeserializeObject<AADTokenResponse>(responseString);
}
}
我认为在这种情况下,FormUrlEncodedContent
是错误的选择,您应该改用 StringContent
,类似于:
var content = new StringContent(HttpUtility.UrlEncode(values), Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://URL.com/Token", content);
原因是,我认为 FormUrlEncodeContent 没有接受添加内容类型的重载。
另一种选择是切换到使用 SendAsync 而不是 PostAsync,因为 SendAsync 具有一些额外的灵活性。
在您的代码中,在您获得 JSON 字符串 responseString
之后,请尝试以下代码,而不是 returning 它。
...
string responseString = await response.Content.ReadAsStringAsync();
response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(responseString, Encoding.UTF8, "application/json");
return response;
您需要将您的方法 return 值从 Task<Object>
更改为 Task<HttpResponseMessage>
编辑:
要访问属性,请安装 Newtonsoft.Json 包并尝试以下代码。
var jsonString = ...
JObject jo = JObject.Parse(jsonString);
Console.WriteLine(jo["access_token"]);
我正在使用 C# 中的 HttpClient 尝试将 SSO(单点登录)集成到我们的一些自定义应用程序中。
我已经在我们的 JavaScript 应用程序中成功地做到了这一点,但是我在将它集成到我们的一些 Umbraco 网站时遇到了一些困难。
到目前为止我的代码:
using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
using Newtonsoft.Json;
using System.Collections.Generic;
using Umbraco.Web;
using Umbraco.Web.WebApi;
namespace Umbraco.WebApi
{
public class TestController : UmbracoApiController
{
public HttpClient client = new HttpClient();
[HttpPost]
public async Task<Object> GetRefreshToken(Token t)
{
try {
string refToken = t.refresh_token;
var values = new Dictionary<string, string>
{
{ "grant_type", "refresh_token" },
{ "client_id", "CLIENTID" },
{ "client_secret", "CLIENTSECRET" },
{ "refresh_token", refToken }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://URL.org/Token", content);
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
} catch(HttpRequestException e) {
return e;
}
}
public class Token
{
public string refresh_token { get; set; }
}
public class AuthData
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_int { get; set; }
public string refresh_token { get; set; }
public string userName { get; set; }
public string client_id { get; set; }
public DateTime issued { get; set; }
public DateTime expires { get; set; }
}
}
}
它成功 return 我想要的数据,但 returned 数据存在问题(已删除敏感数据):
<z:anyType xmlns:d1p1="http://www.w3.org/2001/XMLSchema" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" i:type="d1p1:string">
{"access_token":"XXXXXXXX","token_type":"bearer","expires_in":1199,"refresh_token":"XXXXXX","userName":"XXXXXX","as:client_id":"XXXXX",".issued":"Fri, 20 Sep 2019 13:23:48 GMT",".expires":"Fri, 20 Sep 2019 13:43:48 GMT"}
</z:anyType>
它似乎也被 return 编辑为 XML 而不是 JSON?
C# 不是我最擅长的语言,所以我可能完全错了。
感谢任何帮助。
解决此问题的方法之一是通过添加正确的请求 headers
在您的响应中专门请求 json 格式Accept: application/json
像这样尝试
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
现在,如果服务器关注请求 header,它将 return 返回给您 json。 它可能默认为 xml,因为在您的请求中没有这样的 header 或者服务器仅支持 returning xml 响应。
编辑:如果您无法让服务器到达 return json,您可以将 xml 字符串响应转换为 json 字符串。看看这个example。转换后,您可以从您的控制器正常 return 您的 json 字符串。
编辑:
好的,试试下面这个示例:
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("client_id", ""),
new KeyValuePair<string, string>("scope", ""),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("redirect_uri", ""),
new KeyValuePair<string, string>("code", ""),
new KeyValuePair<string, string>("client_secret","")
});
AADTokenResponse TokenResponse = null;
string _baseAddress = string.Format("https://yourTargetDomain.com/");
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = await client.PostAsync("targetApiSegment", content);
if (responseMessage.IsSuccessStatusCode)
{
var responseString = await responseMessage.Content.ReadAsStringAsync();
TokenResponse = JsonConvert.DeserializeObject<AADTokenResponse>(responseString);
}
}
我认为在这种情况下,FormUrlEncodedContent
是错误的选择,您应该改用 StringContent
,类似于:
var content = new StringContent(HttpUtility.UrlEncode(values), Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://URL.com/Token", content);
原因是,我认为 FormUrlEncodeContent 没有接受添加内容类型的重载。
另一种选择是切换到使用 SendAsync 而不是 PostAsync,因为 SendAsync 具有一些额外的灵活性。
在您的代码中,在您获得 JSON 字符串 responseString
之后,请尝试以下代码,而不是 returning 它。
...
string responseString = await response.Content.ReadAsStringAsync();
response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(responseString, Encoding.UTF8, "application/json");
return response;
您需要将您的方法 return 值从 Task<Object>
更改为 Task<HttpResponseMessage>
编辑:
要访问属性,请安装 Newtonsoft.Json 包并尝试以下代码。
var jsonString = ...
JObject jo = JObject.Parse(jsonString);
Console.WriteLine(jo["access_token"]);