MVC: как вернуть строку в виде JSON
чтобы сделать процесс отчетности о ходе выполнения немного более надежным и отделить его от запроса/ответа, я выполняю обработку в службе Windows и сохраняю предполагаемый ответ на файл. Когда клиент начинает опрашивать обновления, предполагается, что контроллер возвращает содержимое файла, какими бы они ни были, в виде строки JSON.
содержимое файла предварительно сериализуется в JSON. Это для того, чтобы ничего не было стоя на пути ответа. Никакая обработка не должна происходить (за исключением чтения содержимого файла в строку и возврата его), чтобы получить ответ.
Я изначально, хотя это было бы довольно просто, но это оказался не тот случай.
В настоящее время мой метод контроллера выглядит так:
контроллер
Обновлено
[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);
}
и скрипач возвращает это как сырье ответ
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;
}
}
4 ответов:
проблема, я считаю, заключается в том, что результат действия Json предназначен для получения объекта (вашей модели) и создания HTTP-ответа с содержимым в виде данных в формате JSON из вашего объекта модели.
то, что вы передаете в метод JSON контроллера, является JSON-форматированным string object, поэтому он" сериализует " строковый объект в JSON, поэтому содержимое HTTP-ответа окружено двойными кавычками (я предполагаю, что это проблема.)
Я думаю, что вы можете изучить использование результата действия содержимого в качестве альтернативы результату действия 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 контроллера, но недостаток заключается в том, что вы будете де-сериализовать, а затем повторно сериализовать данные, которые могут будьте ненужны для ваших целей.
вам просто нужно вернуть стандартный 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); }
Да, это без каких-либо дополнительных проблем, чтобы избежать необработанной строки 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но между ними нет никакой связи.
все ответы здесь дают хороший и рабочий код. Но кто-то будет недоволен, что они все используют
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);
Comments