我可以在返回带模型的 MVC 视图时添加 json 响应吗?

Can I add a json response when returning an MVC view with model?

有没有办法添加一个 JSON 结果,当控制器使用 return 视图(模型)时,该结果将被 AJAX.BeginForm 的 OnSuccess 或 OnFailure 选项消耗语法?

一切都是非常标准的 C#/MVC。 Ajax.BeginForm 看起来像这样

@using (Ajax.BeginForm("AnyAction", "Home", null,
    new AjaxOptions
    {
        HttpMethod = "Post",
        OnBegin = "OnBegin",
        OnFailure = "OnFailure(xhr, status)",
        OnSuccess = "OnSuccess(xhr, status)"
    },
    new { id = "myform" }))

OnSuccess 和 OnFailure 脚本是这样定义的

    function OnSuccess(xhr, status) {
        console.log("OnSuccess");
    }
    function OnFailure(xhr, status) {
        console.log("OnFailure");       
    }

控制器return是这样的

    HttpContext.Response.StatusCode = (int)HttpStatusCode.NotAcceptable;
    return View(model);

我可以将 HTTPStatusCode(OK 或 Not OK)注入 HTTPContext.Response,这将触发 OnSuccess 或 OnFailure javascript 函数。据此我知道我可以操纵响应流,但无论如何要向 HTTPContext.Response 添加 JSON 响应,以便 OnSuccess 或 OnFailure 可以使用它。

如何在使用 return View(model) 语法时将其传递给 OnSuccess 函数?

dynamic jsonMessage;
jsonMessage = new { param1 = "ModelState", param2 ="Error", param3 = "Error Message" };

一些快速笔记:

这不是要求,只是一个问题。

我已经在项目的其他地方使用 Return JSON(jsonMessage, JsonRequestBehavior.AllowGet),不需要帮助。

由于您的 JSON 很小,您可以使用

添加 JSON 字符串作为响应 header

HttpContext.Response.AddHeader("json", "json_string");

然后可以从 OnSuccess/Failure 方法中的 header 值访问它。

我想跟进我的最终解决方案。首先,我们需要将 Ajax.BeginForm 属性 的 OnSuccess 定义调整为如下所示。我尝试了几种变体,但这个确切的代码是唯一有效的代码。

@using (Ajax.BeginForm("AddUserRole", "AppRoles", null,
    new AjaxOptions
    {
        HttpMethod = "Post",
        OnBegin = "OnBegin",
        OnFailure = "OnFailure(xhr, status)",
        OnSuccess = "OnSuccess(data, status, xhr)"
    },
    new { id = "myform" }))

接下来 OnSuccess 的 javascript 看起来像这样。有几点需要注意;首先,向下显示的控制器可以 return JsonResult 或视图/模型。只要 HttpResponseStatus 正常,无论 return 编辑了哪个,OnSuccess 函数都会被触发。如果控制器 return 是 View/Model,数据参数将包含整个渲染视图,而我想要的 json 将在 XHR 参数中。要使用 json 响应,必须使用 getResponseHeader 将其提取出来,然后序列化为 JSON。之后,我们可以将其作为常规的旧 JSON 对象使用。

function OnSuccess(data, status, xhr) {
    console.log("OnSuccess");
    // this is for capturing from the Response header WHEN the controller returns a view
    var srchMessage = xhr.getResponseHeader("srchMessage")
    if (srchMessage != null) {
        var srchJson = JSON.parse(srchMessage);
        console.log("srchMessage:param1" + srchJson.param1);
        return;
    }
    // this is for capturing the json WHEN the controller returns a JsonResult
    if (xhr.responseJSON != null) {
        console.log("xhr.responseJSON.param1" + xhr.responseJSON.param1);
    }
}

MVC 控制器可以 return 'short' JsonResult 或完整视图,看起来有点像这样

public ActionResult AjaxTest(AppModel model)
{
    if (model.status == "ReturnView")
    {
        jsonMessage = new { param1 = "param1", param2 = "param2", param3 = "param3" };
        string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(jsonMessage);
        HttpContext.Response.AddHeader("srchMessage", jsonString);
        HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
        return View(model);
    }

    if (model.status == "ReturnJSON")
    {
        jsonMessage = new { param1 = "param1", param2 = "param2", param3 = "param3" };
        HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
        return Json(jsonMessage, JsonRequestBehavior.AllowGet);
    }
}

我不确定我为什么要这样做,我应该为不同的操作设置单独的控制器,但如果您想这样做,这就是可以做到的。