views:

68

answers:

3

My controllers all extend a basic UserAwareController class, that exposes GetCurrentUser() method. I would like any call to this method to redirect to the login page if the user is not already logged in.

Can I accomplish this by throwing some exception from this method? How can I cause a redirect to happen when this exception is thrown?

+2  A: 

While I think that you should change approach to solution about authorization, you can stay with it and use this code:

public partial class BaseUserAwareController : Controller
{
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (GetCurrentUser() == null)
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }
}

If your project is not too big, think about changing it to use [Authorize]. If you used it, it would be only:

[Authorize]
public partial class UserAwareController : Controller
{

}

You may think that this is not that big difference, but [Authorize] handles also some caching issues (returning cached response when you are not authorized anymore).

Install MVC 2 and create new MVC 2 web application. It contains authorization logic that you can propably use in your application.

LukLed
Can you point me towards a link that explains Authorization and how to properly use the Authorize keyword? I don't understand how I bind it to my authentication scheme (mine uses open ID).
ripper234
@ripper234: Here is an article about FormsAuthentication and what you have to do to use [Authorize] attribute: http://blog.codevelop.dk/post/2007/11/24/ASPNET-20-Forms-authentication-Keeping-it-customized-yet-simple.aspx You can propably modify it to use OpenId.
LukLed
I tried using Authorize, it looks rather promising except then I came across this issue: http://stackoverflow.com/questions/2724271/using-a-colon-in-return-url-with-forms-authentication-the-return-url-specif
ripper234
+1  A: 

Why not just use the Redirect or RedirectToAction methods to redirect to your login page:

public ActionResult GetCurrentUser()
{
  if (user is not logged in)
  {
      Redirect("/LoginPage");
   }
}

EDIT: Or do the check in the base controller OnActionExecuting:

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (GetCurrentUser() == null)
        {
            (filterContext.Controller as BaseController).Redirect("/Login");
        }

        base.OnActionExecuting(filterContext);
    }

}

http://forums.asp.net/t/1239842.aspx is also a good reference to this topic as well.

amurra
And what if action doesn't need to call GetCurrentUser?
LukLed
He didn't ask for that case, just the case if GetCurrentUser was called
amurra
Does Redirect throw an exception? I don't want to repeat the code that checks "if (GetCurrentUser() == null) Redirect" in every method. I prefer to just use "GetCurrentUser()", and if there is no 'current user' then I want a redirect action (via an exception).
ripper234
@ripper234: You don't have to repeat it in every controller. You just place it in base controller.
LukLed
Redirect will take you to the URI you specify which will contain the action to return the login page. You could put this check in the base controller in the OnActionExecution method and redirect them there
amurra
All redirects in ASP.NET are done through exceptions afaik .. so this will break execution and redirect.
Tigraine
@Tigraine - in Asp.NET MVC you can also return a Redirect result.
ripper234
+1  A: 

In your base controller, override OnActionExecuting. This gives you access to the ActionExecutingContext, which contains the HttpContext and thus the Response.

You can then redirect the user based on whatever logic you want like so:

<ActionContext>.HttpContext.Response.Redirect(<Your Url>)

I forget the name of the context variable offhand, but it's in the method signature.

Tejs