asp.net-mvcasp.net-mvc-3asp.net-mvc-2razorchild-actions

ASP .Net MVC 3: Child Action and Redirect


I need to display the registration form and login form on the home page.

If validation fails on these two forms, I need to display proper errors on the home page.

But if there was no error, the user must be redirected to the secured Dashboard.

To accomplish this, I am using child action on the home page like this:

@Html.Action("Register", "Membership")

It work perfectly as expected if there are any errors, as it is able to re-render the partial view with the proper model that has validation state information.

But if there was no error, when it tries to redirect, it throws an error stating that:

Child actions are not allowed to perform redirect actions.

Is there any way around this? I am sure there is a way to put registration and login forms on the homepage. Most probably I don't know since I am quite new to ASP .Net MVC.

Could you point me in the right direction here?


Solution

  • One way to do this is to use ajax forms for the login and registration bits and, instead of returning a RedirectResult when the submission is valid, return some json which a bit of client-side script will watch out for and use to do a redirect for you.

    Here's a simplified example.

    Controller:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.ComponentModel.DataAnnotations;
    using MvcApplication12.Models;
    
    namespace MvcApplication12.Controllers
    {
        public class HomeController : Controller
        { 
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult Register()
            {
                return PartialView(new UserDetails());
            }
    
            [HttpPost]
            public ActionResult Register(UserDetails details)
            {
                if (ModelState.IsValid)
                {
                    return Json(new {redirect = true, url = Url.Action("Index","Dashboard")});
                }
                else
                {
                    return PartialView(details); 
                }
            } 
        }
    }
    

    Home page 'Index' view:

    @{
        ViewBag.Title = "Index";
    }
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    <script type="text/javascript">
        function checkForRedirect(data)
        {
            if (data.redirect && data.url)
            {
                location.href = data.url;
            }
        }
    </script>
    
    <p>Home page stuff.....</p>
    
    <div id="RegistrationArea">
        @Html.Action("Register")
    </div>
    
    <p> Home page stuff.....</p>
    

    Registration form 'Register' partial view:

    @model MvcApplication12.Models.UserDetails
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    @using (Ajax.BeginForm(new AjaxOptions()
    {
        HttpMethod = "POST",
        Url = Url.Action("Register", "Home"),
        OnSuccess = "checkForRedirect(data)",
        UpdateTargetId = "RegistrationArea",
        InsertionMode = InsertionMode.Replace
    }))
    {
        @Html.LabelFor(m => m.UserName)
        @Html.EditorFor(m => m.UserName) 
        @Html.ValidationMessageFor(m => m.UserName)
    
        @Html.LabelFor(m => m.Password)
        @Html.EditorFor(m => m.Password) 
        @Html.ValidationMessageFor(m => m.Password)
    
        <input type="submit" />
    }