views:

28

answers:

1

I have a UserAccountController that takes routes like this "/{username}/{action}".

I'd like to create some functionality so that I can take a user to an account-specific page without knowing their username up front. I'd like to be able to use the URL "/your/{action}" which would catch the fact that "your" was sent as their username, get their real username (because they are logged in), and redirect them to "/their-actual-username/{action}".

I could do this in each of the controller actions, but I'd rather have it happen some place earlier that would do this for all of the controller actions. I attempted to do this in the Controller's Initialize method by changing the RouteData.Values["username"] to the real username then attempting to Response.RedirectToRoute(RouteData); Response.End() but that always took me to the wrong place (some completely wrong route).


Updated: Thanks to BuildStarted for leading me to this answer:

public class UserAccountController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);

        if ((string) filterContext.RouteData.Values["username"] != "your") 
            return;

        var routeValues = new RouteValueDictionary(filterContext.RouteData.Values);
        routeValues["username"] = UserSession.Current.User.Username;
        filterContext.Result = new RedirectToRouteResult(routeValues);
    }
}
+1  A: 

You can use the FilterAttribute with IActionFilter to accomplish what you want.

public class UserFilterAttribute : FilterAttribute, IActionFilter  {
    public void OnActionExecuted(ActionExecutedContext filterContext) {
    }

    public void OnActionExecuting(ActionExecutingContext filterContext) {
        var username = filterContext.RouteData.Values["username"];
        var realUserName = ""; //load from database
        filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { controller = "Users", action = "Index", username = realUserName }));
    }
}

Then on your ActionResult in your controller you could apply [UserFilter] to the action.

[UserFilter]
public ActionResult UnknownUserHandler() {
    return View();
}

This should get you the results you're looking for. Any questions please post :)

BuildStarted
I didn't want to use an attribute because I wanted it to apply to all of the actions on that controller. But you pointed me at the OnActionExecuting method which is also on Controller and that worked great.
EliThompson
Nice, glad to be of help.
BuildStarted