There is only one control Home with a bunch of action. It also has a private method bool IsFinish (), which returns the state of the system. At a certain stage (namely when IsFinish start returning true) is necessary, what any callable method redirected to public ActionResult Result (). In principle, I do not care where this will Result - in the current controller or the other. Overview all actions forward to it.
How can this be implemented?
You could use an action filter of asp.net mvc to do it. An action filter is an attribute that you can apply to a controller action -- or an entire controller -- that modifies the way in which the action is executed, for sample:
public class RedirectFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get the home controller in a safe cast
var homeController = filterContext.Controller as Controller;
// check if it is home controller and not Result action
if (homeController != null && filterContext.ActionDescriptor.ActionName != "Result")
{
if (homeController.IsFinish())
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", "Home" },
{ "action", "Result" }
});
}
}
base.OnActionExecuting(filterContext);
}
}
And apply it on your controller:
[RedirectFilter] // apply to all actions
public class HomeController : Controller
{
public ActionResult Home()
{
/* your action's code */
}
public ActionResult Home()
{
/* your action's code */
}
public ActionResult Home()
{
/* your action's code */
}
public ActionResult Result()
{
return View();
}
}
Related
I would like to return an Action to an other Controller
Example: i have 2 controlers:
[Route("myurl"]
public class HomeController : Controller
{
public ActionResult Action1()
{
if (...)
{
return Action2(); //working fine i will keep my route
}
else
{
return OtherController.Action3(); //Don't know how to do it here.
}
}
public ActionResult Action2()
{
return View();
}
}
and
public class OtherController : Controller
{
public ActionResult Action3()
{
return View();
}
}
It's working if the Action is inside the same controller but wish to return the Action1 from HomeController to Action3 from OtherController.
I want to keep the same route (not a redirection to an other route).
Any idea ?
Have you tried using this RedirectToAction?
return RedirectToAction("ACTION_NAME", "CONTROLLER_NAME", new { area = "" });
I found out:
I need to return like that :
return DependencyResolver.Current.GetService<OtherController>().Action3();
[Route("myurl"]
public class HomeController : Controller
{
public ActionResult Action1()
{
if (...)
{
return Action2(); //working fine i will keep my route
}
else
{
return DependencyResolver.Current.GetService<OtherController>().Action3();
}
}
public ActionResult Action2()
{
return View();
}
}
return RedirectToAction("ActionName", "ControllerName");
You can do this by calling the below method of controller class protected internal RedirectToRouteResult RedirectToAction(string actionName, string controllerName); For your requirement the code inside the else block would look like base.RedirectToAction("ACtion3","OtherController");
I have following code in my controller actions. I have more than 15 controllers and more than 40 actions through out the application. Example:
//Check if USER SESSION object is available
if (Session["user"] != null)
{
return View();
}
else
{
return RedirectToAction("logout", "Home", new { area = "Common", value = "SessionTimeOut" });
}
I don't want to repeat the if statement for all 40 actions. Any better way of doing this?
You'll want to look at AuthenticationFilters (see here for an MVC walkthrough).
FTA:
public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext) {
//For demo purpose only. In real life your custom principal might be retrieved via different source. i.e context/request etc.
filterContext.Principal = new MyCustomPrincipal(filterContext.HttpContext.User.Identity, new []{"Admin"}, "Red");
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) {
var color = ((MyCustomPrincipal) filterContext.HttpContext.User).HairColor;
var user = filterContext.HttpContext.User;
if (!user.Identity.IsAuthenticated)
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
FTA usage:
public class HomeController : Controller
{
//***here is where it's applied. you can also do this globally in Global.asax if preferred***
[CustomAuthentication]
public ActionResult Index()
{
return View();
}
}
To supplement the answer pointing to the [CustomAuthentication] attribute, you could create a base controller class, like this:
[CustomAuthentication]
public class BaseController : Controller
{
}
Which your 15 controllers can inherit from:
public HomeController : BaseController
Now, by default, every action method on the derived controllers will execute the [Authorize] attribute, so for the action methods which do not require authorization, you can mark them with the [AllowAnonymous] attribute:
public class HomeController : BaseController
{
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
}
I have a handful of Actions in my ASP.NET MVC site that have one parameter. The first lines of code on all these actions checks that the parameter is not null, and if it is, redirect to a page that allows them to choose a value for the parameter.
For example:
public ActionResult Summary(string client)
{
if (String.IsNullOrEmpty(client))
return RedirectToAction("Select");
return View();
}
I'd like to create an attribute that does something like the above code, so I don't have to repeat it in every action. Something like:
[ClientRequired]
public ActionResult Summary(string client)
{
return View();
}
And then the ClientRequiredAttribute would check the value of the client parameter, and if it's empty/null, redirect to the select client page. Is such an attribute possible?
-shnar
Yes, it is possible.
It would be something like this:
public class ClientRequiredAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
object parameter = null;
filterContext.ActionParameters.TryGetValue("client", out parameter);
var client = parameter as string;
if (string.IsNullOrEmpty(client))
{
var urlHelper = new UrlHelper(filterContext.Controller.ControllerContext.RequestContext);
var url = urlHelper.Action("Select", "ControllerName");
filterContext.Result = new RedirectResult(url);
}
}
}
PS: Not tested, but it should work.
In ASP.NET MVC 5 you can use attribute routing.
http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx
public class ReviewsController : Controller
{
// eg: /reviews
[Route("reviews")]
public ActionResult Index() { ... }
// eg: /reviews/5
[Route("reviews/{reviewId}")]
public ActionResult Show(int reviewId) { ... }
// eg: /reviews/5/edit
[Route("reviews/{reviewId}/edit")]
public ActionResult Edit(int reviewId) { ... }
}
I have MVC4 applicaton, which contains http-handler, and I want to redirect user to my first page
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
HttpHandler
public class MyPublicHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (condition)
{
var controller = new HomeController();
controller.Index(); // redirect and execute
}
// or something like that
if (condition)
{
ExecutePage("http://myWebSite/Home/Index")
}
}
}
Thanks!
I have tried two ways: Response.Redirect() which does nothing, as well as calling a new method inside of the Base Controller that returns an ActionResult and have it return RedirectToAction()... neither of these work.
How can I do a redirect from the OnActionExecuting method?
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
...
if (needToRedirect)
{
...
filterContext.Result = new RedirectResult(url);
return;
}
...
}
It can be done this way as well:
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{"controller", "Home"},
{"action", "Index"}
}
);
Create a separate class,
public class RedirectingAction : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
if (CheckUrCondition)
{
context.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
controller = "Home",
action = "Index"
}));
}
}
}
Then,
When you create a controller, call this annotation as
[RedirectingAction]
public class TestController : Controller
{
public ActionResult Index()
{
return View();
}
}
If the redirected controller inherit from the same baseController where we override the OnActionExecuting method cause recursive loop. Suppose we redirect it to login action of account controller, then the login action will call OnActionExecuting method and redirected to the same login action again and again
... So we should apply a check in OnActionExecuting method to check weather the request is from the same controller if so then do not redirect it login action again. here is the code:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
try
{
// some condition ...
}
catch
{
if (filterContext.Controller.GetType() != typeof(AccountController))
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary {
{ "controller", "Account" },
{ "action", "Login" }
});
}
}
}