What's the correct way to get the controller name and action from an httpContext object? I can see the values in the debug, but I don't seem to be able to get to them in the object code?
Please remember to mark replies as answers if you find them useful =8)
From an HttpContext object? You can't; you require at minimum a RequestContext
object. If you have a RequestContext object, you can call RouteData.GetRequiredString("controller") / GetRequiredString("action").
No ideas, Levi? I'm trying to move my authorisation object/permissions matrix into the back end SQL server database, rather than have values hard-coded in my app.
Thx MH
Please remember to mark replies as answers if you find them useful =8)
The code sample on your blog looks fine. The AuthorizeCore() is the appropriate place to perform these custom checks. (I've not actually tested your code, but the general pattern seems good.)
What exactly are you looking for feedback on? You need access to more information than is available in the AuthorizeCore() method?
Note that the reason the AuthorizeCore() method gives you so little to work with is that it hooks authorization in both the MVC pipeline and in the output caching pipeline. (If a page is cached, the AuthorizeCore() method still runs before the page
is served from the cache, even though the rest of the MVC pipeline is inactive.)
If you need to inspect the action method itself or otherwise get information inaccessible from the AuthorizeCore() method, you can do that from within the OnAuthorization() method. If you go this route, be sure that the request isn't cached, else the OnAuthorization()
method won't be called when the page is fetched from the cache. But if you were doing something as complicated as this, you probably weren't output caching these particular actions anyway. :)
public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter {
public void OnAuthorization(AuthorizationContext filterContext) {
// disable caching for this request
filterContext.HttpContext.Response.Cache.SetNoServerCaching();
filterContext.HttpContext.Response.Cache.SetNoStore();
bool isAuthorized = ...; // your custom logic here
if (!isAuthorized) {
filterContext.Result = new HttpUnauthorizedResult(); // or a RedirectResult, etc.
}
}
}
What's the correct way to get the controller name and action from an httpContext object? I can see the values in the debug, but I don't seem to be able to get to them in the object code?
HttpContextWrapper ht = new HttpContextWrapper(context);
string forum = RouteTable.Routes.GetRouteData(ht).Values["controller"].ToString();
http://forums.asp.net/t/1533299.aspx
"And whoever is removed away from the Fire and admitted to Paradise, he indeed is successful." (The Holy Quran)
Excellent Windows VPS Hosting Imran Baloch MVP, MVB, MCP, MCTS, MCPD
The code sample on your blog looks fine. The AuthorizeCore() is the appropriate place to perform these custom checks. (I've not actually tested your code, but the general pattern seems good.)
What exactly are you looking for feedback on? You need access to more information than is available in the AuthorizeCore() method?
Note that the reason the AuthorizeCore() method gives you so little to work with is that it hooks authorization in both the MVC pipeline and in the output caching pipeline. (If a page is cached, the AuthorizeCore() method still runs before the page
is served from the cache, even though the rest of the MVC pipeline is inactive.)
Not my code, but something someone else suggested. Somewhere in there (AFAIK the AuthorizeCore seems to be the correct place) I want to get hold of the calling controller and action. I can then cross-ref that with the user roles and see if that is in a
DB table entry which contains the controller/action/access privs. This way I can moe the authorisation out of being hard-coded in the app and into a DB table where it can then be administered by the apps admin functions. My current problem is that I'm struggling
to get those controller and action names. And no, I wouldn't want any caching on these pages, the whole app is very dynamic =8)
I'll have a look at what I've got here over the next few days, thx for the feedback, any more is always welcome (WRT my comments here).
Cheers - MH
Please remember to mark replies as answers if you find them useful =8)
This way I can move the authorisation out of being hard-coded in the app and into a DB table where it can then be administered by the apps admin functions
Exactly the right approach. Keep us posted on your progress.
HttpContextWrapper ht = new HttpContextWrapper(context);
string forum = RouteTable.Routes.GetRouteData(ht).Values["controller"].ToString();
http://forums.asp.net/t/1533299.aspx
Thanks, but that doesn't quite work (slightly my bad, I'm afraid) it's an HttpContextBase not an HttpContext that the authorizecore supplies, so that won't wrap, unfortunately
Please remember to mark replies as answers if you find them useful =8)
The code sample on your blog looks fine. The AuthorizeCore() is the appropriate place to perform these custom checks. (I've not actually tested your code, but the general pattern seems good.)
What exactly are you looking for feedback on? You need access to more information than is available in the AuthorizeCore() method?
Note that the reason the AuthorizeCore() method gives you so little to work with is that it hooks authorization in both the MVC pipeline and in the output caching pipeline. (If a page is cached, the AuthorizeCore() method still runs before the page
is served from the cache, even though the rest of the MVC pipeline is inactive.)
If you need to inspect the action method itself or otherwise get information inaccessible from the AuthorizeCore() method, you can do that from within the OnAuthorization() method. If you go this route, be sure that the request isn't cached, else the OnAuthorization()
method won't be called when the page is fetched from the cache. But if you were doing something as complicated as this, you probably weren't output caching these particular actions anyway. :)
bool isAuthorized = ...; // your custom logic here
if (!isAuthorized) {
filterContext.Result = new HttpUnauthorizedResult(); // or a RedirectResult, etc.
}
}
}
public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter {
public void OnAuthorization(AuthorizationContext filterContext) {
// disable caching for this request
filterContext.HttpContext.Response.Cache.SetNoServerCaching();
filterContext.HttpContext.Response.Cache.SetNoStore();
bool isAuthorized = ...; // your custom logic here
if (!isAuthorized) {
filterContext.Result = new HttpUnauthorizedResult(); // or a RedirectResult, etc.
}
}
Hope this helps!
Thanks Levi, that seems to have cracked it, can I check a couple of things, please, before I close this down:-
Here is my implementation of your code, any glaring mistakes?
public class LeviAuth : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
// disable caching for this request
filterContext.HttpContext.Response.Cache.SetNoServerCaching();
filterContext.HttpContext.Response.Cache.SetNoStore();
bool isAuthorized = filterContext.HttpContext.User.Identity.IsAuthenticated;
if (isAuthorized)
{
if (filterContext.RouteData.Values["controller"] != null &&
filterContext.RouteData.Values["action"] != null &&
filterContext.RouteData.Values["controller"].ToString().Trim().Length > 0 &&
filterContext.RouteData.Values["action"].ToString().Trim().Length > 0)
{
string controller = filterContext.RouteData.Values["controller"].ToString();
string action = filterContext.RouteData.Values["action"].ToString();
// blah blah blah
if (action == "Search")
{
isAuthorized = false;
}
if (action == "Create" && filterContext.HttpContext.User.Identity.Name.ToUpper() == "FRED")
{
isAuthorized = false;
}
// blah blah blah
}
else
{
// if we can't get the action and controller names, deny
isAuthorized = false;
}
}
if (!isAuthorized)
{
filterContext.Result = new HttpUnauthorizedResult(); // or a RedirectResult, etc.
}
}
}
I will replace the // blah blah blah section with a call to a DB function, passing in the user's role list, the controller and action name and getting back a boolean.
Would the controller and action name ever not exist/get passed in? I couldn't see any reason why not, but I was wondering - even if it were a default action, from the URL's point of view, this would still generate an action name in the RouteData, wouldn't
it?
Also, output caching is something that's explicitly stated, isn't it? As you suggested, and as far as I am aware, I am not explicitly using it (nor would I want to as each page in this app is always dynamic) but are there any gotchas that I can check for
that might enable it somehow?
Cheers for your help, much apprec, sorry it's taken quite a few days to get to this, but I've been working like crazy all this year
MH
Please remember to mark replies as answers if you find them useful =8)
Mad-Halfling
Participant
1438 Points
729 Posts
Getting Controller and Action from HttpContext
Mar 08, 2010 09:54 AM|LINK
What's the correct way to get the controller name and action from an httpContext object? I can see the values in the debug, but I don't seem to be able to get to them in the object code?
levib
Star
7702 Points
1099 Posts
Microsoft
Re: Getting Controller and Action from HttpContext
Mar 08, 2010 04:47 PM|LINK
From an HttpContext object? You can't; you require at minimum a RequestContext object. If you have a RequestContext object, you can call RouteData.GetRequiredString("controller") / GetRequiredString("action").
What's your particular scenario?
Mad-Halfling
Participant
1438 Points
729 Posts
Re: Getting Controller and Action from HttpContext
Mar 08, 2010 09:25 PM|LINK
Ah, joy, attention from the illustrious Levi. I'm working from this http://schotime.net/blog/index.php/2009/02/17/custom-authorization-with-aspnet-mvc/ using the CustomAuthorizeAttribute in the AuthorizeCore override - if you can offer any pearls of wisdom I'd be much obliged.
Mad-Halfling
Participant
1438 Points
729 Posts
Re: Getting Controller and Action from HttpContext
Mar 10, 2010 07:01 AM|LINK
No ideas, Levi? I'm trying to move my authorisation object/permissions matrix into the back end SQL server database, rather than have values hard-coded in my app.
Thx MH
levib
Star
7702 Points
1099 Posts
Microsoft
Re: Getting Controller and Action from HttpContext
Mar 10, 2010 07:40 AM|LINK
The code sample on your blog looks fine. The AuthorizeCore() is the appropriate place to perform these custom checks. (I've not actually tested your code, but the general pattern seems good.)
What exactly are you looking for feedback on? You need access to more information than is available in the AuthorizeCore() method?
Note that the reason the AuthorizeCore() method gives you so little to work with is that it hooks authorization in both the MVC pipeline and in the output caching pipeline. (If a page is cached, the AuthorizeCore() method still runs before the page is served from the cache, even though the rest of the MVC pipeline is inactive.)
If you need to inspect the action method itself or otherwise get information inaccessible from the AuthorizeCore() method, you can do that from within the OnAuthorization() method. If you go this route, be sure that the request isn't cached, else the OnAuthorization() method won't be called when the page is fetched from the cache. But if you were doing something as complicated as this, you probably weren't output caching these particular actions anyway. :)
public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) { // disable caching for this request filterContext.HttpContext.Response.Cache.SetNoServerCaching(); filterContext.HttpContext.Response.Cache.SetNoStore(); bool isAuthorized = ...; // your custom logic here if (!isAuthorized) { filterContext.Result = new HttpUnauthorizedResult(); // or a RedirectResult, etc. } } }Hope this helps!
imran_ku07
All-Star
45815 Points
7698 Posts
MVP
Re: Getting Controller and Action from HttpContext
Mar 10, 2010 08:22 AM|LINK
HttpContextWrapper ht = new HttpContextWrapper(context);
string forum = RouteTable.Routes.GetRouteData(ht).Values["controller"].ToString();
http://forums.asp.net/t/1533299.aspx
Excellent Windows VPS Hosting
Imran Baloch MVP, MVB, MCP, MCTS, MCPD
Mad-Halfling
Participant
1438 Points
729 Posts
Re: Getting Controller and Action from HttpContext
Mar 10, 2010 05:46 PM|LINK
Not my code, but something someone else suggested. Somewhere in there (AFAIK the AuthorizeCore seems to be the correct place) I want to get hold of the calling controller and action. I can then cross-ref that with the user roles and see if that is in a DB table entry which contains the controller/action/access privs. This way I can moe the authorisation out of being hard-coded in the app and into a DB table where it can then be administered by the apps admin functions. My current problem is that I'm struggling to get those controller and action names. And no, I wouldn't want any caching on these pages, the whole app is very dynamic =8)
I'll have a look at what I've got here over the next few days, thx for the feedback, any more is always welcome (WRT my comments here).
Cheers - MH
ricka6
All-Star
15070 Points
2272 Posts
Microsoft
Moderator
Re: Getting Controller and Action from HttpContext
Mar 11, 2010 08:06 PM|LINK
Exactly the right approach. Keep us posted on your progress.
Mad-Halfling
Participant
1438 Points
729 Posts
Re: Getting Controller and Action from HttpContext
Mar 18, 2010 10:02 AM|LINK
Thanks, but that doesn't quite work (slightly my bad, I'm afraid) it's an HttpContextBase not an HttpContext that the authorizecore supplies, so that won't wrap, unfortunately
Mad-Halfling
Participant
1438 Points
729 Posts
Re: Getting Controller and Action from HttpContext
Mar 18, 2010 10:16 AM|LINK
Thanks Levi, that seems to have cracked it, can I check a couple of things, please, before I close this down:-
Here is my implementation of your code, any glaring mistakes?
public class LeviAuth : FilterAttribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) { // disable caching for this request filterContext.HttpContext.Response.Cache.SetNoServerCaching(); filterContext.HttpContext.Response.Cache.SetNoStore(); bool isAuthorized = filterContext.HttpContext.User.Identity.IsAuthenticated; if (isAuthorized) { if (filterContext.RouteData.Values["controller"] != null && filterContext.RouteData.Values["action"] != null && filterContext.RouteData.Values["controller"].ToString().Trim().Length > 0 && filterContext.RouteData.Values["action"].ToString().Trim().Length > 0) { string controller = filterContext.RouteData.Values["controller"].ToString(); string action = filterContext.RouteData.Values["action"].ToString(); // blah blah blah if (action == "Search") { isAuthorized = false; } if (action == "Create" && filterContext.HttpContext.User.Identity.Name.ToUpper() == "FRED") { isAuthorized = false; } // blah blah blah } else { // if we can't get the action and controller names, deny isAuthorized = false; } } if (!isAuthorized) { filterContext.Result = new HttpUnauthorizedResult(); // or a RedirectResult, etc. } } }I will replace the // blah blah blah section with a call to a DB function, passing in the user's role list, the controller and action name and getting back a boolean.
Would the controller and action name ever not exist/get passed in? I couldn't see any reason why not, but I was wondering - even if it were a default action, from the URL's point of view, this would still generate an action name in the RouteData, wouldn't it?
Also, output caching is something that's explicitly stated, isn't it? As you suggested, and as far as I am aware, I am not explicitly using it (nor would I want to as each page in this app is always dynamic) but are there any gotchas that I can check for that might enable it somehow?
Cheers for your help, much apprec, sorry it's taken quite a few days to get to this, but I've been working like crazy all this year
MH