developer tip

MVC : 문자열을 JSON으로 반환하는 방법

optionbox 2020. 11. 23. 08:03
반응형

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

문제는 Json 작업 결과가 개체 (모델)를 가져와 모델 개체의 JSON 형식 데이터로 콘텐츠가 포함 된 HTTP 응답을 생성하기위한 것이라고 생각합니다.

하지만 컨트롤러의 Json 메서드에 전달하는 것은 JSON 형식의 문자열 개체 이므로 문자열 개체를 JSON으로 "직렬화"하므로 HTTP 응답의 내용이 큰 따옴표로 묶여 있습니다 (I ' m 그것이 문제라고 가정).

본질적으로 HTTP 응답에 대한 원시 콘텐츠를 이미 사용할 수 있으므로 Json 작업 결과 대신 Content 작업 결과를 사용할 수 있다고 생각합니다.

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때문에, 나를 위해 작동하지 않는 JsonResultContentResult모두 상속을 ActionResult하지만, 그들 사이에 관계가 없다.


All answers here provide good and working code. But someone would be dissatisfied that they all use ContentType as return type and not JsonResult.

Unfortunately JsonResult is using JavaScriptSerializer without option to disable it. The best way to get around this is to inherit JsonResult.

I copied most of the code from original JsonResult and created JsonStringResult class that returns passed string as application/json. Code for this class is below

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

Example usage:

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

Use the following code in your controller:

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

and in JavaScript:

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

참고URL : https://stackoverflow.com/questions/9777731/mvc-how-to-return-a-string-as-json

반응형