Подтвердить что ты не робот

MVC: как вернуть строку в JSON

Чтобы сделать процесс отчетов о проделанной работе немного более надежным и отделить его от запроса/ответа, я выполняю обработку в службе Windows и сохраняю предполагаемый ответ на файл. Когда клиент начинает опрос обновлений, предполагается, что контроллер возвращает содержимое файла, независимо от того, что они есть, как строка JSON.

Содержимое файла предварительно сериализуется в JSON. Это должно гарантировать, что на пути ответа нет ничего. Никакой обработки не должно произойти (не дочитав содержимое файла в строке и возвращая его), чтобы получить ответ.

Я изначально, хотя это было бы довольно просто, но это не так.

В настоящее время мой метод контроллера выглядит следующим образом:

Controller

Обновление

[HttpPost]
public JsonResult UpdateBatchSearchMembers()
{
    string path = Properties.Settings.Default.ResponsePath;
    string returntext;
    if (!System.IO.File.Exists(path))
        returntext = Properties.Settings.Default.EmptyBatchSearchUpdate;
    else
        returntext = System.IO.File.ReadAllText(path);

    return this.Json(returntext);
}

И Fiddler возвращает это как сырой ответ

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 19 Mar 2012 20:30:05 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 3.0
Cache-Control: private
Content-Type: application/json; charset=utf-8
Content-Length: 81
Connection: Close

"{\"StopPolling\":false,\"BatchSearchProgressReports\":[],\"MemberStatuses\":[]}"

AJAX

Обновление

Далее, скорее всего, будет изменено позже, но пока это работает, когда я генерирую класс ответа и возвращаю его как JSON, как обычный человек.

this.CheckForUpdate = function () {
var parent = this;

if (this.BatchSearchId != null && WorkflowState.SelectedSearchList != "") {
    showAjaxLoader = false;
    if (progressPending != true) {
        progressPending = true;
        $.ajax({
            url: WorkflowState.UpdateBatchLink + "?SearchListID=" + WorkflowState.SelectedSearchList,
            type: 'POST',
            contentType: 'application/json; charset=utf-8',
            cache: false,
            success: function (data) {
                for (var i = 0; i < data.MemberStatuses.length; i++) {
                    var response = data.MemberStatuses[i];
                    parent.UpdateCellStatus(response);
                }
                if (data.StopPolling = true) {
                    parent.StopPullingForUpdates();
                }
                showAjaxLoader = true;
            }
        });
        progressPending = false;
    }
}
4b9b3361

Ответ 1

Я считаю, что проблема заключается в том, что результат действия Json предназначен для того, чтобы взять объект (вашу модель) и создать HTTP-ответ с содержимым в виде данных в формате JSON из вашего объекта модели.

То, что вы передаете контроллеру Json, однако, является строковым объектом в формате JSON, поэтому он "сериализует" строковый объект JSON, поэтому содержимое ответа HTTP окружено двойными кавычками (Я предполагаю, что это проблема).

Я думаю, что вы можете изучить результат действия Content в качестве альтернативы результату action Json, поскольку у вас по существу уже имеется необработанный контент для ответа HTTP.

return this.Content(returntext, "application/json");
// not sure off-hand if you should also specify "charset=utf-8" here, 
//  or if that is done automatically

Другой альтернативой было бы десериализовать результат JSON от службы в объект, а затем передать этот объект методу Json контроллера, но недостатком является то, что вы будете де-сериализовать и затем повторно сериализовать данные, которые может быть ненужным для ваших целей.

Ответ 2

Вам просто нужно вернуть стандартный ContentResult и установить ContentType в "application/json". Вы можете создать для него пользовательский ActionResult:

public class JsonStringResult : ContentResult
{
    public JsonStringResult(string json)
    {
        Content = json;
        ContentType = "application/json";
    }
}

И затем верните экземпляр:

[HttpPost]
public JsonResult UpdateBatchSearchMembers()
{
    string returntext;
    if (!System.IO.File.Exists(path))
        returntext = Properties.Settings.Default.EmptyBatchSearchUpdate;
    else
        returntext = Properties.Settings.Default.ResponsePath;

    return new JsonStringResult(returntext);
}

Ответ 3

Да, это без каких-либо дополнительных проблем, чтобы избежать raw string json, это он.

    public ActionResult GetJson()
    {
        var json = System.IO.File.ReadAllText(
            Server.MapPath(@"~/App_Data/content.json"));

        return new ContentResult
        {
            Content = json,
            ContentType = "application/json",
            ContentEncoding = Encoding.UTF8
        };
    } 

ПРИМЕЧАНИЕ: обратите внимание, что тип возвращаемого метода JsonResult для меня не работает, поскольку JsonResult и ContentResult оба наследуют ActionResult, но между ними нет отношения.

Ответ 4

Все ответы здесь дают хороший и рабочий код. Но кто-то будет недоволен, что все они используют ContentType качестве возвращаемого типа, а не JsonResult.

К сожалению, JsonResult использует JavaScriptSerializer без возможности отключить его. Лучший способ обойти это - унаследовать JsonResult.

Я скопировал большую часть кода из оригинального JsonResult и создал JsonStringResult класса, который возвращает переданную строку в качестве application/json. Код для этого класса ниже

public class JsonStringResult : JsonResult
    {
        public JsonStringResult(string data)
        {
            JsonRequestBehavior = JsonRequestBehavior.DenyGet;
            Data = data;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
                String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException("Get request is not allowed!");
            }

            HttpResponseBase response = context.HttpContext.Response;

            if (!String.IsNullOrEmpty(ContentType))
            {
                response.ContentType = ContentType;
            }
            else
            {
                response.ContentType = "application/json";
            }
            if (ContentEncoding != null)
            {
                response.ContentEncoding = ContentEncoding;
            }
            if (Data != null)
            {
                response.Write(Data);
            }
        }
    }

Пример использования:

var json = JsonConvert.SerializeObject(data);
return new JsonStringResult(json);

Ответ 5

от контроллера:

return Json (new {success = string}, JsonRequestBehavior.AllowGet);

и в случае успеха Javascript: function (data) {var response = data.success; .... }....}