MVC:如何将字符串作为JSON返回

时间:2012-03-19 20:50:08

标签: asp.net-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);
}

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

5 个答案:

答案 0 :(得分:111)

我认为,问题在于Json操作结果旨在获取一个对象(您的模型),并使用内容作为模型对象的JSON格式数据创建HTTP响应。

你传递给控制器​​的Json方法的是一个JSON格式的字符串对象,所以它将字符串对象“序列化”为JSON,这就是为什么HTTP的内容响应被双引号包围(我假设这是问题)。

我认为您可以考虑使用Content操作结果作为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方法,但缺点是您将反序列化然后重新序列化数据,可能没有必要为你的目的。

答案 1 :(得分:40)

您只需返回标准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);
}

答案 2 :(得分:2)

Yeah that's it without no further issues, to avoid raw string json this is it.

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

NOTE: please note that method return type of JsonResult is not working for me, since JsonResult and ContentResult both inherit ActionResult but there is no relationship between them.

答案 3 :(得分:0)

这里的所有答案都提供了良好且有效的代码。但有人会不满意他们都使用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);

答案 4 :(得分:0)

在您的控制器中使用以下代码:

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

和JavaScript:

success: function (data) {
    var response = data.success;
    ....
}