Как вернуть объект Json из метода С#

Я пытаюсь исправить метод ASP.NET WebAPI, где требуется ответ Json. Однако вместо этого он возвращает строку.

Первоначально это был формат XML, но я добавил эту строку в код mvc в App_Start\WebApiConfig.cs, чтобы вернуть Json по умолчанию.

config.Formatters.Remove(config.Formatters.XmlFormatter);

Мы обновили метод c # следующим образом, чтобы использовать NewtonSoft:

public string Get()
{
    string userid = UrlUtil.getParam(this, "userid", "");
    string pwd = UrlUtil.getParam(this, "pwd", "");
    string resp = DynAggrClientAPI.openSession(userid, pwd);

    JsonSerializer ser = new JsonSerializer();
    string jsonresp = JsonConvert.SerializeObject(resp);

    return resp;
}

Соотв. var возвращается как строковый тип:

"{status:\"SUCCESS\",data:[\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\"]}"

и jsonresp var выглядит так:

"\"{status:\\\"SUCCESS\\\",data:[\\\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\\\"]}\""

и в инструментах разработчика Chrome F12 объект данных:

""{status:\"SUCCESS\",data:[\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\"]}""

и в Консольных инструментах результат angular.fromJson(data):

"{status:"SUCCESS",data:["4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d"]}"

Я хотел бы получить несколько советов о том, как правильно возвращать объект Json, а НЕ в любом типе строки.


UPDATE

Перехватив переменную resp и воспользовавшись приведенным ниже предложением г-на Чу, я могу успешно получить хороший чистый объект Json на клиенте. Ключ в том, что resp должен содержать двойные кавычки вокруг обеих пар ключ: значение:

public HttpResponseMessage Get()
{
    string userid = UrlUtil.getParam(this, "userid", "");
    string pwd = UrlUtil.getParam(this, "pwd", "");
    string resp = DynAggrClientAPI.openSession(userid, pwd);

    resp = "{\"status\":\"SUCCESS\",\"data\":[\"194f66366a6dee8738428bf1d730691a9babb77920ec9dfa06cf\"]}";  // TEST !!!!!           

    var response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(resp, System.Text.Encoding.UTF8, "application/json");
    return response;
}

в консоли Chrome ответ:

Object {status: "SUCCESS", data: Array[1]}
data: Array[1]
status: "SUCCESS"
__proto__: Object

Ответ 1

resp уже является строкой JSON, но недействителен JSON (ключи не заключены в кавычки ("). Если он возвращается в angular, метод JavaScript JSON.parse() не удалось десериализовать его. Однако вы можете использовать JSON.NET для десериализации его в JObject и сериализовать его снова в действительный JSON и создать свой собственный HttpResponseMessage...

public HttpResponseMessage Get()
{
    string userid = UrlUtil.getParam(this, "userid", "");
    string pwd    = UrlUtil.getParam(this, "pwd", "" );

    string resp = DynAggrClientAPI.openSession(userid, pwd);
    var jObject = JObject.Parse(resp);

    var response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
    return response;
}

Или вы можете просто вернуть JObject и иметь веб-интерфейс для его сериализации для вас...

public JObject Get()
{
    string userid = UrlUtil.getParam(this, "userid", "");
    string pwd    = UrlUtil.getParam(this, "pwd", "" );

    string resp = DynAggrClientAPI.openSession(userid, pwd);
    var jObject = JObject.Parse(resp);

    return jObject;
}

В любом случае вызов Web API должен вернуть этот JSON, который теперь действителен...

{
  "status": "SUCCESS",
  "data": [
    "4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d"
  ]
}

В коде angular вам придется откопать идентификатор сеанса, который хранится в массиве с именем data...

userService.openUserSession(rzEnvJson).then(function (response) {
    var sessionResponse = response.data; // or simply response, depending if this is a promise returned from $http
    $rootScope.rgSessionVars.sessionID = sessionResponse.data[0];
});

Ответ 2

Я не вижу, как это связано с AngularJS, но ваша проблема проста. Ваш объект данных закодирован JSON. Таким образом, вы почти наверняка сможете получить доступ к data.JsonRequestBehavior, и это будет 1. Но поле данных внутри него AGAIN JSON-закодировано. Вы должны декодировать его, прежде чем пытаться его использовать - это просто строка, когда вы добираетесь до этого обратного вызова:

var myData = angular.fromJson(data.Data);
console.log(myData.data);

Обратите внимание, что ваш объект data.Data сам по себе является другой оболочкой - массивом. Вы почти наверняка хотите, чтобы myData.data[0] заходил в это поле sessionID...

Ответ 3

Ключ к тому, что здесь происходит, в комментарии, сделанном Майком Чилом; сериализация происходит дважды, один раз в коде OP и один раз в Asp.Net WebAPI. Вот почему вместо объекта Json возвращается строка.

Я сталкивался с тем же самым. Вот пример Привет, мир, показывающий проблему. Сначала я сделал что-то вроде этого:

[Route("getall")]
public string GetAllItems()
{
    var result = new
    {
        x = "hello",
        y = "world"
    };
    return JsonConvert.SerializeObject(result);
}

Затем я попытался сделать что-то вроде этого, думая, что мне нужно вернуться IHttpActionResult, чтобы решить эту проблему:

[Route("getall")]
public IHttpActionResult GetAllItems()
{
    var result = new
    {
        x = "hello",
        y = "world"
    };
    return Ok(JsonConvert.SerializeObject(result));
}

Оба этих действия контроллера дали мне строку, а не объект Json, который я хотел; вот и я так:

"{\"x\":\"hello\",\"y\":\"world\"}"

Наконец, я увидел комментарий Майка и понял, что мне нужно возвращать объект .Net напрямую и просто позволить WebAPI обрабатывать сериализацию. Поэтому вместо того, чтобы возвращать это:

return Ok(JsonConvert.SerializeObject(result));

вернуть это:

return Ok(result);

Тогда я получил ожидаемый результат:

{"x":"hello","y":"world"}