Reputation: 21
Short verion: need ViewUserControl (i.e., Login Form) to post to self and be able to redirect (i.e., on successful login), or return original View (i.e., Home/Index) with validation summary and not interfere with other ViewUserControls on the page.
Also, HomeController/Index should have minimal knowledge of Login Form's inner workings. Ideally, Html.RenderAction("Login","User"), or similar, is all that's required.
At the moment, stuck on redirect giving "Child actions are not allowed to perform redirect actions." I know why, but wondering if there is a way around, or another way I should be doing this.
Details of what I am trying to achieve:
- encapsulate a Login (or any) Form to be reused across site
- post to self
- when Login/validation fails, show original page with Validation Summary
- (some might argue to just post to Login Page and show Validation Summary there; if what I'm trying to achieve isn't possible, I will just go that route)
- when Login succeeds, redirect to /App/Home/Index
- also, want to:
- stick to PRG principles
- avoid ajax
- keep Login Form (UserController.Login()) as encapsulated as possible; avoid having to implement HomeController.Login() since the Login Form might appear elsewhere
All but the redirect works. My approach thus far has been:
Home/Index
includes Login Form:<%Html.RenderAction("Login","User");%>
User/Login ViewUserControl<UserLoginViewModel>
includes:
using(Html.BeginForm()){}
- includes hidden form field
"userlogin"="1"
public class UserController : BaseController {
...
[AcceptPostWhenFieldExists(FieldName = "userlogin")]
public ActionResult Login(UserLoginViewModel model, FormCollection form){
if (ModelState.IsValid) {
if(checkUserCredentials()) {
setUserCredentials()
return this.RedirectToAction<Areas.App.Controllers.HomeController>(x => x.Index());
}
else {
return View();
}
}
...
}
Works great when: ModelState or User Credentials fail -- return View() does yield to Home/Index and displays appropriate validation summary.
(I have a Register Form on the same page, using the same structure. Each form's validation summary only shows when that form is submitted.)
Fails when: ModelState and User Credentials valid -- RedirectToAction<>() gives following error:
"Child actions are not allowed to perform redirect actions."
It seems like in the Classic ASP days, this would've been solved with Response.Buffer=True
. Is there an equivalent setting or workaround now?
Btw, running: ASP.Net 4, MVC 2, VS 2010, Dev/Debugging Web Server
I hope all of that makes sense.
So, what are my options? Or where am I going wrong in my approach? tia!
Upvotes: 2
Views: 991
Reputation: 1495
Ancient question, but this is basically exactly the same thing as I'm doing right now, and my searches have still revealed no answers that match all criteria; I don't see why it is so hard to have the login process completely encapsulated like this, but maybe I'm simply missing a clearly written example.
My solution, which works perfectly, is to simply use the old standard
System.Web.HttpContext.Current.Response.Redirect(url, true);
...in the controller for the login process.
Posting it because it works, it maintains encapsulation, and it's slightly less horrible than the return-a-view-containing-a-Javascript-redirect solution I've seen, but I'd still like a better idea of how to achieve this sort of packaging in a more MVC way.
Upvotes: 0
Reputation: 4194
I would go with a partial View (e.g. "_Login.cshtml" or "_Login.ascx") that can be placed on the MasterPage/_Layout. Inside the partial View you write a form tag that posts to an Action on a Controller (lets say "AuthController" and the action "LogIn"). To remember where you came from
This is how the action could look like this:
public ActionResult LogIn(string username, string password)
// name the id's of the form elements as the parameters
{
if(YouAuthMethodHere(username, password))
{
return View("Welcome");
}
else
{
return Redirect(HttpContext.Current.Request.Referer.AbsolutUri);
}
}
When you successfully authenticated the user the view named "Welcome.cshtml"/"Welcome.aspx" is returned otherwise redirected from where the form was submitted.
Note: The referer could be null (e.g. if not a browser like fiddler or a script is making the request) so there is a bit of error handling left.
Upvotes: 0