Obscure Bugs: ASP.NET MVC Child Actions
/ 3 min read
Found this post helpful?
Buy me a coffeeTable of Contents
When I first heard of the ability to perform child actions in ASP.NET MVC, the purest in me wanted to kick puppies and punch babies. Luckily the pragmatist in me was able to talk me down and embrace the awesomeness. Child actions are one of the greatest features of ASP.NET MVC, and I couldn’t imagine building a large scale application without them. As great as they are, they need to be used sparingly. This post will show you how you may shoot yourself in the foot utilizing child actions incorrectly. Let’s start with the error, and then I’ll guide you to how we got here.
Scary isn’t it?! What the heck is a 404.15 error?
Widgets!
Child actions are great for widgets. A widget is a small feature of an application that can appear on multiple views and is the culmination of backend logic and common UI. Do you need a counter? What about a RSS feed display? What about outstanding messages? A widget is most likely our answer. Let’s create a widget.
Our controller action method:
[ChildActionOnly]public ActionResult Secure(){ return PartialView();}Our view:
<div class="col-md-4"> <h2>Secured</h2> <p>This is a secured mini-box</p></div>I admit this is a contrived widget, but it will do for our example.
Location, Location, Location.
Since we are building a widget, we most likely want it appearing across multiple views. You have two options now.
- Place the call to Html.Action across all views.
- Place the call to Html.Action in our Layout.
Not wanting to repeat ourselves, we put the child action in our layout.
<div class="container body-content"> @RenderBody() @Html.Action("Secure", "Home") <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer></div>Security
Oh no! We just got the requirement that our widget needs to be secured. So we modify our action method to look like this.
[Authorize][ChildActionOnly]public ActionResult Secure(){ return PartialView();}Easy right?
Boom goes the dynamite!
Ugh! This can’t be happening! What happened?
By putting a secured resource directly on our layout, we never give our application a chance to render any page without triggering an authentication request. The side effect is we get an infinite redirect. I’ve also seen this error manifest on IIS as a 403 error.
Workarounds
The easiest workaround is to move the authentication from an attribute into our action method.
[ChildActionOnly]public ActionResult Secure(){ if (User.Identity.IsAuthenticated) return Content(""); return PartialView();}Be careful when securing your child actions.Understanding that mishandling child actions can result in strange errors can put you in a better position to solve your issue, rather than being stumped by these head scratching messages. Hope you enjoyed this post, and please leave me a comment if you’ve ever run into this obscure bug. I would love to hear your story.