ActionFilterAttribute redirect to action method with parameter
I have made a custom access checking ActionFil开发者_运维技巧terAttribute which I want to redirect to an error page if they do not have sufficient access. Here is what I have so far.
RouteValueDictionary routeValues = new RouteValueDictionary(new {
action = "Error",
controller = "Home",
error = new Error(HttpStatusCode.Unauthorized, "You do not have sufficient access to complete your request.", (HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : ""), DateTime.Now)
});
filterContext.Result = new RedirectToRouteResult(routeValues);
Here is the error page action method
public ActionResult Error(Error error)
However when the route redirects to the action method, the 'error' paramater is null, how do I do this without the paramater being null?
You cannot pass complex object parameters when redirecting. You could pass it's constituent properties and leave the default model binder do the job of reconstructing it. So assuming you have the following model:
public class Error
{
public string Message { get; set; }
public HttpStatusCode Status { get; set; }
public string UserHost { get; set; }
public DateTime Date { get; set; }
}
you could redirect like this:
var routeValues = new RouteValueDictionary(new
{
action = "Error",
controller = "Home",
Message = "You do not have sufficient access to complete your request.",
Status = HttpStatusCode.Unauthorized,
// Remark: never use HttpContext.Current :
UserHost = filterContext.HttpContext.Request.UserHostAddress,
Date = DateTime.Now.ToString("u")
});
filterContext.Result = new RedirectToRouteResult(routeValues);
Also for handling authorization I would recommend you writing a custom AuthorizeAttribute
instead of a custom ActionFilterAttribute
. It's semantically more correct.
Your problem is caused because of this: when declaring routes (usually in global.asax(.cs)), the HttpContext.Current is null ALWAYS! so the action will always receive a null as error parameter.
Try to change your code this way:
- in global.asax(.cs) declare only the route with controller and action in it. That is quite enough for route.
- in Home controller's Error() action, define the code which displays the "access denied" message of your need (usually done by returning Content("access denied message goes here")).
- if your action filter is able to successfully redirect to this route, than it should be fine to leave the way it is.
Hope this helps!
BTW, you can just return the ActionResult you need right from the action filter - so instead of redirecting to the Error action (I suppose using Redirect or RedirectToAction), you can just return the Content("access denied message goes here").
Either of these will work just fine.
精彩评论