Возврат JSON через WebApi - PullRequest
       5

Возврат JSON через WebApi

1 голос
/ 20 сентября 2019

Я использую HttpClient в C #, чтобы попытаться интегрировать 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; }

    }
  }
}

, который успешно возвращает данные, которые мне нужны, но есть проблемы с возвращенными данными (Удаленоdata):

<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>

Кажется также, что он возвращается как XML вместо JSON?

C # не самый сильный из моих языков, поэтому я могу быть совершенно неправ.

Любая помощь приветствуется.

Ответы [ 3 ]

2 голосов
/ 20 сентября 2019

В вашем коде после получения строки JSON responseString вместо ее возврата попробуйте следующий код.

...
string responseString = await response.Content.ReadAsStringAsync();
response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(responseString, Encoding.UTF8, "application/json");
return response;

Вам необходимо изменить значение, возвращаемое методом, с Task<Object> на Task<HttpResponseMessage>

Редактировать:

Чтобы получить доступ к свойствам, установите пакет Newtonsoft.Json и попробуйте следующий код.

var jsonString = ...
JObject jo = JObject.Parse(jsonString);
Console.WriteLine(jo["access_token"]);
2 голосов
/ 20 сентября 2019

Одна из вещей, которую вы можете сделать для решения этой проблемы, - это специально запросить формат json в своем ответе, добавив заголовки corrent-запроса

Accept: application/json

, попробуйте так, как надо

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

Теперь, если сервер обращает внимание на заголовки запроса, он вернет вам json.Это может быть значение по умолчанию xml, поскольку в вашем запросе такого заголовка нет ИЛИ сервер поддерживает только возврат ответов xml.

EDIT: если вы не можете заставить сервер вернуть json, вы можете преобразовать свой ответ строки xmlв строку json.Взгляните на этот пример .После преобразования вы можете нормально вернуть строку 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);
                }
            }
0 голосов
/ 20 сентября 2019

Я думаю, что в этом случае 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 обладает некоторой дополнительной гибкостью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...