secretAgentB
secretAgentB

Reputation: 1279

MVC3 two partial views in one view

I am trying to learn MVC 3 & Razor and I'm stuck here for 3 hours now. This is what I have

MVC project created using the default template with Account registration and all that good stuff from the template. What I'm trying to do is have both registration page and login page in the index of the HomeController so I created a partial view for both Register (_RegisterPartial) and LogOn (_LogOnPartial). When I go to the index page, I see the registration and login forms which is good but when I try to login or register it goes into an infinite loop.

My HomeController looks like this;

// **************************************
// Registration
// **************************************

public ActionResult DoRegister()
{
    return PartialView("_Register");
}

[HttpPost]
public ActionResult DoRegister(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        // Attempt to register the user
        MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email, model.UserProfile);

        if (createStatus == MembershipCreateStatus.Success)
        {
            FormsService.SignIn(model.UserName, false); // createPersistentCookie
            return View("Success");
        }
        else
        {
            ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
        }
    }

    // If we got this far, something failed, redisplay form
    ViewBag.PasswordLength = MembershipService.MinPasswordLength;
    return View(model);
}


// **************************************
// Login
// **************************************

public ActionResult DoLogin()
{
    return PartialView("_Login");
}

[HttpPost]
public ActionResult DoLogin(LogOnModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        if (MembershipService.ValidateUser(model.UserName, model.Password))
        {
            // logged in
            FormsService.SignIn(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl))
            {
                Redirect(returnUrl);
            }
            else
            {
                View("Success");
            }
        }
        else
        {
            // Not logged in
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }

    // If we got this far, something failed, redisplay form
    return View("Success");
}

and my cshtml looks like this;

@{
    ViewBag.Title = "Home Page";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@if (Request.IsAuthenticated)
{
    @Html.ActionLink("Log Off", "LogOff", "Account")
}
else
{
    Html.RenderAction("DoLogin");
    Html.RenderAction("DoRegister");
}

Regards,

Ryan

Upvotes: 2

Views: 6266

Answers (2)

Ahmad
Ahmad

Reputation: 24847

I can't exactly replicate your situation but I would say that you partial forms are not posting correctly. Have a look a rendered html of the page and check where the forms are being posted to. My guess is that they are being posted to the Index action. Coupled with the redirect, I think that is where the infinite loop is coming from.

My guess is the html rendered for both forms are similar and posting to the same action i.e. <form action="/" method="post">, since they are being rendered by the HomeController's Index action.

Change the partial forms (_Login.cshtml and _Register.cshtml) and explicitly state which action/controller combination to post to (more on Html.BeginForm from MSDN)

@using (Html.BeginForm("DoLogin","Home"))    {/*snipped*/} //in _Login.cshtml
@using (Html.BeginForm("DoRegister","Home")) {/*snipped*/} //in _Register.cshtml

Also I would change the Html.RenderAction calls to

Html.RenderPartial("_Login");
Html.RenderPartial("_Register");

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038810

Do you read exception messages?

A public action method 'Register' was not found on controller 'AudioRage.Controllers.HomeController'

Now look at the code of HomeController you've posted. Do you see a Register action on it? I don't.

So add one:

public ActionResult Register()
{
    ...
}

In your HomeController you have an action called Register but action is only accessible through POST verbs as it is decorated with the [HttpPost] attribute:

[HttpPost]
[ActionName("Register")]
public ActionResult Index(RegisterModel model)

so you cannot invoke it with a GET verb on /Home/Register.

Upvotes: 3

Related Questions