4

我有一个视图,我从中调用另一个视图以在我的 html 中的脚本标记内呈现一些 json:

public ActionResult App()
{
  return View();
}

public JsonResult SomeJsonData()
{
  // ... here goes the code that generates the model
  return Json(model, JsonRequestBehavior.AllowGet);
}

在我的 App.cshtml 文件中,我有这样的内容:

<script type='text/javascript'>
  var myJsonData = @Html.Action("SomeJsonData", "MyController");
</script>

问题是有时当我在浏览器中重新加载页面时(现在使用 Chrome 20)它会显示所有标记,如果我转到开发人员工具中的网络选项卡,我可以看到页面请求的 Content-Type属于“应用程序/json”类型。如果我只是重新加载页面,那么它会正确加载(内容类型应该是“text/html”)。

关于为什么会发生这种情况的任何想法?或者我做错了什么?

4

4 回答 4

2

当您返回 a 时,JsonResult您正在将响应 Content-Type 修改为application/json。因此,您首先调用App返回 View 的控制器操作,并且显然将 Content-Type 设置为text/html并在返回的视图内调用该SomeJsonData操作,该操作对先前的内容类型进行废话并将其修改为application/json. 当然最后一个获胜,这就是用户代理在一天结束时看到的:application/json.

因此,以下是如何进行:

public ActionResult App()
{
    // ... here goes the code that generates the model
    var model = ...

    return View(model);
}

在您的强类型视图中:

@model MyViewModel
<script type="text/javascript">
    var myJsonData = @Html.Raw(Json.Encode(Model));
</script>
于 2012-07-10T19:10:05.520 回答
1

其实我刚刚发现了另一个相关的问题

为 JsonResult 调用 @Html.Action 会更改我在父模板中的响应类型

在发帖之前我找不到任何东西。

我要采取的方法只是在返回 json 数据时更改内容类型:

public JsonResult SomeJsonData(bool returnAsHtml = false)
{
  // ... here goes the code that generates the model
  return returnAsHtml ?Json(model, "text/html", JsonRequestBehavior.AllowGet) : Json(model, JsonRequestBehavior.AllowGet);
}

在 App.cshtml 上

<script type='text/javascript'>
  var myJsonData = @Html.Action("SomeJsonData", "MyController", new {returnAsHtml = true});
</script>

而且我还添加了一个标志,以允许从其他需要应用程序/json 响应的地方调用 actionmethod。

于 2012-07-10T19:22:29.160 回答
0

就像其他人所说的那样,返回 JSON 的操作正在更改响应的内容类型。

我可以通过使用 HtmlHelper 将 JSON 放入页面来解决此问题。我避免使用控制器和动作;我的 HtmlHelper 正在调用静态方法。这个解决方案可能不会在所有情况下都有效,并且有点像 hack,但是您可以避免以这种方式将数据放入一堆视图模型中。

namespace System.Web.Mvc.Html
{
   public static class JsonDataProviderHelper
   {
      public static MvcHtmlString JsonDataProvider(this HtmlHelper helper, JsonDataType jsonDataType)
      {
         switch (jsonDataType)
         {
            case JsonDataType.YARDSALE_MINI_CALENDAR:
               var yardsales = SalesEventCrud.GetByMonthForJavascript(null, MvcApplication.CurrentPortalId);
               return new MvcHtmlString(JsonConvert.SerializeObject(SalesEventCrud.GetByMonthForJavascript(null, MvcApplication.CurrentPortalId)));

            default:
               return new MvcHtmlString("");
         }
      }

      public enum JsonDataType
      {
         YARDSALE_MINI_CALENDAR
      }
   }
}

我正在使用 json.net 进行序列化。我有switch声明是因为我计划使用这个帮助器在其他情况下也返回 JSON。

在页面中:

<script type="text/javascript">
   jQuery(document).ready(function () {
      setupSmallSidebarCalendar(@Html.JsonDataProvider(JsonDataProviderHelper.JsonDataType.YARDSALE_MINI_CALENDAR));
   });
</script>

在页面中,数据以直接 JSON 形式写入,因此不需要对数据进行其他解析/按摩。

于 2013-04-27T20:10:43.947 回答
0

@Daran 找到了原因 - ContentType 被最后完成的任何内容覆盖。他的解决方案应该有效,但是如果您仍然喜欢 Action 方法模式,您应该能够执行以下操作,并在返回之前简单地更改 ContentType。它仍然是 JSON 数据,但内容类型与 HTML 视图配合得很好。

    [HttpPost]
    public JsonResult GetJson(int someId, int foobar)
    {
        JsonResult result = CreateResult(someId, foobar);
        result.ContentType = "text/html";
        return result;
    }

不利的一面是,这有点奇怪和/或意外的行为。例如,如果您通过 AJAX 调用端点,我怀疑这会起作用。但它看起来几乎可以工作,如果它在共享代码库中,可能会引起一些混乱。出于这个原因,如果您这样做,可能值得以不被滥用的方式命名端点。您甚至可以创建一种旨在以这种方式工作而不是使用 JsonResult 的新型 Result。

于 2013-09-17T19:25:16.170 回答