calling @Html.Action for JsonResult changes my res

2019-02-16 14:27发布

问题:

I've got the following controller:

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

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

Then, inside Index.cshtml:

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

What I'm finding is that, when going to this url in my browser, the response content type is application/json; charset=utf-8 which causes the browser to render the html as a string instead of as... a web page.

What's the best way to get around this?

回答1:

The reason to this is that all Html.Action invocations are executed directly. Something like:

  1. Index is called
  2. View result is executed
  3. Hello action is executed, set's ContextType
  4. Index view result is returned
  5. Browser displays the page

You got two options:

  1. Break out the logic which generates "Hello world!" into a regular C# class and invoke it directly in the Index controller action
  2. Load the Hello action through ajax and then display the alert.

Option 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!";
    }
}

Option 2

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

Side note

Internet Explorer is quite aggressive when it comes to caching. The JSON responses will be changed. I therefore recommend that you also specify no cache for the JSON action:

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


回答2:

Just use the overload of Json(...) to set the correct content type.

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

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


回答3:

If you return a JsonResult, via calling the Json() method, it won't return a web page. To return a page, you need to return a ViewResult, via calling the View method. Your method should have a corresponding view template

Check out this link or this one