Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 667
Moon Avatar asked Apr 06 '12 05:04

Moon


3 Answers

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" />
}
like image 61
Duncan Avatar answered Oct 22 '22 15:10

Duncan


You should not use the child actions in that context.

A solution to your problem could be to place two forms in your page one for registration and one for login. The registration form posts to a Register action in a Membership controller, the login action posts to a Login action in the Membership controller.

In case an error occurs in one of the actions you can:

  • Show a dedicated Login/Registration page and use model/validation results to show error messages
  • Redirect to the URL/Action the user was coming from and show an error message you place in TempData
like image 20
saintedlama Avatar answered Oct 22 '22 15:10

saintedlama


Without using javascript for redirect: If you put forms inside your child views,Sometimes if you specify action name and controller name in Beginform helper(inside child view), this problem doesn't happen. for example I changed my child action view like this :

Before :

@using (Html.BeginForm())
{
 ...
}

After :

    @using (Html.BeginForm("InsertComment", "Comments", FormMethod.Post, new { id = "commentform" })) 
{
 ...
}

Now, You can put RedirectAction command inside "InsertComment" action and everything will work.


Two form in one page management:

1.Specify name for Submit button (Each form) (Ex: "submitvalue")

form1:

 <input type="submit" value="login" name="submitValue" class="btn btn-success pull-right" />

form2:

 <input type="submit" value="register" name="submitValue" class="btn btn-success pull-right" />

2.Make two action for these forms. (Ex: "Register" and "Login")

[HttpPost]
     public ActionResult Login(LoginVM model, string submitValue)
            {
                if (submitValue == "login")
                { 
               //Do Something
                }  
                 ...
             }


[HttpPost]
public ActionResult Register(RegisterVM model, string submitValue)
            {
                if (submitValue == "register")
                { 
               //Do Something
                 }  
                ...
             }
  • If you click on register or login button in forms, both of actions are called but with "if" statement we determine whichone is our target.
like image 1
MortezaDalil Avatar answered Oct 22 '22 14:10

MortezaDalil