views:

1174

answers:

3

I need an attribute that handles Authorization for my controllers. This is for a facebook application and there are a few hurdles surrounding the problem.

What I really need is the equivalent to a server.transfer but of course that is not an option in ASP MVC. A redirect will not work because of the way facebook consumes the application.

Is there an a way I can re-route from within an ActionFilterAttribute?

public class FbAuthorize : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!Service.SignedIn())
            RouteToAction("Account", "Index"); // Fictional method (I wish it existed)
    }
}
+1  A: 

You could just render the sam view with the same data that the action you want to route to would have rendered. Abstract the code to generate the data back into the model and both methods could use it from there so you reduce the duplication. This won't give you the same URL, but it will give you the view that you want.

tvanfosson
Thanks I did consider this but I have quite a bit of HTML and FBML on the SignIn page so I was hoping for something more graceful
Jamey McElveen
So make it a shared view so you can reuse it from both controllers -- or factor it out into a ViewUserControl so the amount that you need to generate in the view for the controller is minimal.
tvanfosson
+2  A: 

If you're using the facebook developer's toolkit you can implement the basepagehelper's LoadFBMLPage method in an ActionFiler's OnActionExecuting method. (otherwise you'll have to emit the fb:redirect tag yourself). Here's a brief writeup: http://onishimura.com/2009/04/13/facebook-and-aspnet-mvc/

on
Great link. Thanks.
xandy
A: 

Hi,

Here is your "Server.Transfer()" or kind of:

public static class ServerHelper {

  public static void Transfer(ActionExecutingContext filterContext, string url) {

    // Rewrite path
    HttpContext.Current.RewritePath(GetPath(filterContext, url), false);

    IHttpHandler httpHandler = new System.Web.Mvc.MvcHttpHandler();

    // Process request
    httpHandler.ProcessRequest(HttpContext.Current);
    filterContext.HttpContext.Response.End();
  }

  private static string GetPath(ActionExecutingContext filterContext, string url) {
      HttpRequestBase request = filterContext.HttpContext.Request;

      UriBuilder uriBuilder = new UriBuilder(request.Url.Scheme, request.Url.Host, request.Url.Port, request.ApplicationPath);

      uriBuilder.Path += url;

      return filterContext.HttpContext.Server.UrlDecode(uriBuilder.Uri.PathAndQuery);
  }
}

Now, in your filter, just call:

ServerHelper.Transfer(filterContext, "Account/Index");

Cheers

andrecarlucci