Call @Html.Action для JsonResult изменяет мой тип ответа в родительском шаблоне

У меня есть следующий контроллер:

public class HelloController
{
    public ActionResult Index()
    {
        return View()
    }

    public ActionResult Hello()
    {
        return Json(new{ greeting = "hello, world!" }, JsonRequestBehavior.AllowGet);
    }
}

Затем внутри Index.cshtml:

...html stuffs
<script type="text/javascript">
    alert("@Html.Action("Hello")");
</script>

Что я нахожу, так это то, что при переходе к этому URL-адресу в моем браузере тип содержимого ответа application/json; charset=utf-8, который заставляет браузер отображать html в виде строки, а не как... веб-страницу.

Какой лучший способ обойти это?

Ответ 1

Причиной этого является то, что все вызовы Html.Action выполняются напрямую. Что-то вроде:

  • Индекс называется
  • Результат поиска выполнен
  • Выполнено действие Hello, установите ContextType
  • Возвращается результат отображения индексов
  • Браузер отображает страницу

У вас есть два варианта:

  • Разрыв логики, которая генерирует "Привет, мир!". в обычный класс С# и вызывать его непосредственно в действии контроллера индекса.
  • Загрузите действие Hello через ajax, а затем отобразите alert.

Вариант 1

public class HelloController
{
    YourBusiness _yb;

    public HelloController(YourBusiness yb)
    {
        _yb = yb;
    } 
    public ActionResult Index()
    {
        return View(yb.GenerateHello())
    }

    // used for everything but Index
    public ActionResult Hello()
    {
        return Json(new{ greeting = yb.GenerateHello() }, JsonRequestBehavior.AllowGet);
    }
}

public class YourBusiness
{
    public string GenerateHello()
    {
        return "Hello wolrd!";
    }
}

Вариант 2

<script type="text/javascript">
    $.get('@Url.Action("Hello")', function(response) {
        alert(response.greeting);
    }
</script>

Боковое примечание

Internet Explorer довольно агрессивен, когда дело доходит до кеширования. Реакции JSON будут изменены. Поэтому я рекомендую вам также указать кеш для действия JSON:

[OutputCache(Duration = 0, NoStore = true)]
public ActionResult Hello()
{
    return Json(new{ greeting = "hello, world!" }, JsonRequestBehavior.AllowGet);
}

Ответ 2

Просто используйте перегрузку Json(...), чтобы установить правильный тип содержимого.

public class HelloController
{
    public ActionResult Index()
    {
        return View()
    }

    public ActionResult Hello()
    {
        return Json(new{ greeting = "hello, world!" }, "text/html", JsonRequestBehavior.AllowGet);
    }
}

Ответ 3

Если вы вернете JsonResult, вызвав метод Json(), он не вернет веб-страницу. Чтобы вернуть страницу, вам нужно вернуть ViewResult, вызвав метод View. Ваш метод должен иметь соответствующий шаблон представления

Отметьте эту ссылку или this one