views:

721

answers:

3

It appears that calling Html.RenderAction in Asp.Net MVC2 apps can alter the mime type of the page if the child action's type is different than the parent action's.

The code below (testing in MVC2 RTM), which seems sensible to me, will return a result of type application/json when calling Home/Index. Instead of dispylaying the page, the browser will barf and ask you if you want to download it.

My question: Am I missing something? Is this a bug? If so, what's the best workaround?

controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData[ "Message" ] = "Welcome to ASP.NET MVC!";

        return View();
    }

    [ChildActionOnly]
    public JsonResult States()
    {
        string[] states = new[] { "AK", "AL", "AR", "AZ", };

        return Json(states, JsonRequestBehavior.AllowGet);
    }
}

view:

<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<p>
    To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc&lt;/a&gt;.
</p>
<script>
  var states = <% Html.RenderAction("States"); %>;
</script>
+4  A: 

It's not a bug. The JsonResult type is supposed to set the result to JSON, because that's usually what you want.

You don't really want a JSON result here, you want a JSON string. So why not just write that?

[NonAction]
public string States()
{
    string[] states = new[] { "AK", "AL", "AR", "AZ", };

    return new JavaScriptSerializer().Serialize(states);
}
Craig Stuntz
this will work... it just doesn't seem like a child action should be able to change the ContentType of the whole page.
Gabe Moothart
+1  A: 

This can be solved by explicitly forcing the mime type "back" to text/html:

return Json(states, "text/html", JsonRequestBehavior.AllowGet);

It doesn't seem like this should be necessary, though.

Gabe Moothart
That doesn't so much solve the issue as hide it. `JsonResult` still changes `ContentType` here; it just changes it to what you (currently!) expect it to be.
Craig Stuntz
+1  A: 

Like Craig Stuntz said the content type is supposed to change.

A better approach would be calling that action with AJAX and then assigning the returned object to the states variable in the JavaScript code.

çağdaş
Can you suggest a scenario in which this behavior (child action changing page's ContentType) is actually what you want to happen?
Gabe Moothart
@Gabe Moothart, I can't think of a scenario where you'd want that to happen. But the thing is, the problem is not the change of the ContentType. The problem is calling a **Json** Result action while rendering an **HTML** view. JsonResult sets the request objects ContentType property to `application/json` like it's supposed to. But unfortunately, since you call that from an HTML view, the original response's type changes as you see.
çağdaş