2

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

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

5 Comments

I do. He used the ActionNameAttribute.
@Linkgoron, yes he also used [HttpPost] attribute.
That's correct. His problem is understanding the get and post attributes, which is a different problem then the one you stated at first.
@Linkgoron, I've updated my answer to include this information.
Thanks for the reply. I modified my code above but now it goes into an infinite loop. It goes into the register post even if i clicked the login button.
1

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");

3 Comments

Im coming from an ASP.NET webforms background and I want to understand how to wire the events of a partial view to a code. Since in MVC we can't have code behind how do I tell the button what action to execute. Because if I do Html.RenderPartial("_Login"); it renders just fine but when I hit the login button, nothing happens. Do I have to write the login routine to every controller that renders that partial view?
@ryan - the Html.BeginForm that I've placed above says to which controller/action the form needs to be posted to. In general though, I would think that the login form and registration forms will always be posted to the same controller/action combo and in this case the DoLogin and DoRegistration actions of the Home controller. I think you may need to update your question with code of the partial views.
Html.BeginForm("DoLogin","Home") solved it. Thank you so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.