Can anybody please tell me how to handle sessions in asp.net MVC 4. I am aware about this Session variable and I know how to use it.
Session["login"] = true; //We can use it in controller to check the whether user logged in or not.
Above code snippet is enough to handle sessions on small web application. But, what if I have many controllers and actions and I am working on a large application, In this case I cant use session variable in each action.
Is there is any generic place where I can check my session variables or any other solution ?
1st Way:
I used to write a Base Controller class and all other Controllers inherit from it that need to authenticated before access:
public class DefaultController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Session["User"] == null)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = 403;
filterContext.Result = new JsonResult { Data = "LogOut", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
else
filterContext.Result = RedirectToAction("Login", "Account");
}
else
{
//base.Execute(filterContext.RequestContext);
}
}
}
and inherit from Base Controller in the ones for which user must be logged in:
public class LeaveController : DefaultController
{
}
Another way is to write your own authorizaion attribute.
See Filter and Attributes in asp.net mvc
2nd Way:
Here is sample for custom filter attribute, create class which inherits from ActionFilterAttribute:
public class SessionTimeoutAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Session["someValueYouLookFor"] == null)
{
filterContext.Result = new RedirectResult("~/Home/Index"); // redirect to login action
}
else
{
// continue normal execution
}
}
}
and put it on Controller or Action:
[SessionTimeout]
public ActionResult Index()
{
}
Definitely, you can use Authentication filter if you're using MVC 5.
for simplest way, you can have a baseController, and all other controller should inherit that controller, and in baseController you can override that OnActionExecuting event, to verify if session is there or not.
for ex.
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Convert.ToBoolean(Session["login"]))
{
//Authenticated
}
else
{
//Kick to login page
}
}
All other controller should inherit this baseController
public class HomeController : BaseController
{
public ActionResult Index()
{
return View();
}
public ActionResult Test()
{
return View();
}
}
This way, before your action method start executing, it will be verified through baseController's OnActionExecuting event.
Related
How do I use the ASP.NET MVC 2 Preview 2 Futures RequireHttps attribute?
I want to prevent unsecured HTTP requests from being sent to an action method. I want to automatically redirect to HTTPS.
MSDN:
RequireHttpsAttribute
RequireHttpsAttribute Members
RequireHttpsAttribute.HandleNonHttpsRequest Method
How do I use this feature?
I think you're going to need to roll your own ActionFilterAttribute for that.
public class RedirectHttps : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!filterContext.HttpContext.Request.IsSecureConnection) {
filterContext.Result =
new RedirectResult(filterContext.HttpContext.Request.Url.
ToString().Replace("http:", "https:"));
filterContext.Result.ExecuteResult(filterContext);
}
base.OnActionExecuting(filterContext);
}
}
Then in your controller :
public class HomeController : Controller {
[RedirectHttps]
public ActionResult SecuredAction() {
return View();
}
}
You might want to read this as well.
My guess:
[RequireHttps] //apply to all actions in controller
public class SomeController
{
//... or ...
[RequireHttps] //apply to this action only
public ActionResult SomeAction()
{
}
}
[AuthenticateUser]
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[AllowAnonymous]
public ActionResult List()
{
return View();
}
}
How to remove authentication for action named as List? Please advise....
My Custom Filter coding as follow.. i have inherited the FilterAttribute call as well.
Please advise regarding
public class AuthenticateUserAttribute: FilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext context)
{
if (this.IsAnonymousAction(context))
{
}
if (user == "user")
{
// do nothing
}
else
{
context.Result = new HttpUnauthorizedResult(); // mark unauthorized
}
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext context)
{
if (context.Result == null || context.Result is HttpUnauthorizedResult)
{
context.Result = new RedirectToRouteResult("Default",
new System.Web.Routing.RouteValueDictionary{
{"controller", "Home"},
{"action", "List"},
{"returnUrl", context.HttpContext.Request.RawUrl}
});
}
}
}
The below code generate the error message : Error 1 The best overloaded method match for 'MVC5Features.Filters.AuthenticateUserAttribute.IsAnonymousAction(System.Web.Mvc.AuthorizationContext)' has some invalid arguments c:\users\kirupananthan.g\documents\visual studio 2013\Projects\MVC5Features\MVC5Features\Filters\AuthenticateUserAttribute.cs 16 17 MVC5Features
Error 2 Argument 1: cannot convert from 'System.Web.Mvc.Filters.AuthenticationContext' to 'System.Web.Mvc.AuthorizationContext' c:\users\kirupananthan.g\documents\visual studio 2013\Projects\MVC5Features\MVC5Features\Filters\AuthenticateUserAttribute.cs 16 40 MVC5Features
if (this.IsAnonymousAction(context))
Since it is your custom filter, you can extend it to handle AllowAnonymous (if you don't want to use AllowAnonymous, yoy can create own f.e. NoAuthentication):
public class AuthenticateUser : IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
if (this.IsAnonymousAction(filterContext))
{
return;
}
// some code
}
private bool IsAnonymousAction(AuthenticationContext filterContext)
{
return filterContext.ActionDescriptor
.GetCustomAttributes(inherit: true)
.OfType<AllowAnonymousAttribute>()
//or any attr. you want
.Any();
}
}
Try the
[AllowAnonymous]
attribute
Maybe if you specify a specific User Group for that action and in your custom authentication filter allow this group for everything.
In MVC 5 and I quote from http://www.dotnetcurry.com/showarticle.aspx?ID=975
The class CustomOverrideAuthorizationAttribute is inherited from the FilterAttribute class and implements IOverrideFilter. This interface is used to define the filters applied on the controller. The property FiltersToOverride returns the IAuthorizationFilter type. This means that Authorize filter applied on the parent (controller or Global application class) will be overridden
I believe you should remove the attribute from the controller and put it on each action method except List.
So, reading the article that #Bilal posted (Oct 30 '14 at 12:24), it seems there's an elegant way to override filters by class (or interface). You'd have to write a custom attribute for each filter that you want to override, but that may not be a huge problem, if you consider that you probably don't want to override many filters, right?
So, in your question you want to override the AutherizationUser attribute, so you'd implement this class:
public class CustomOverrideAuthenticateUserAttribute :
FilterAttribute, IOverrideFilter
{
public Type FiltersToOverride
{
get
{
return typeof(AuthenticateUserAttribute);
}
}
}
And rewrite your controller as:
[AuthenticateUser]
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[CustomOverrideAuthenticateUser]
public ActionResult List()
{
return View();
}
}
I am currently building a user login system in MVC 5 for practice. What I wanna do is, making a controller only accessable if you have the session "UserId".
Surely, I could just make an if statement in every action, like this:
public ActionResult Index()
{
if (Session["UserId"] != null)
{
return View();
}
else
{
return RedirectToRoute("Home");
}
}
But is there a way I can make that happen with all the actions in the controller?
Bonus info:
I have 2 controllers
- HomeController
- AccountController
You would implement an authorize filter and apply that filter to your controller.
Something like this:
public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
if (filterContext.HttpContext.Session["UserId"] == null)
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
Then you could apply the [CustomAuthentication] attribute to your controller directly, or you can do it by each action in your controller. Something like this:
[CustomAuthentication]//<-- If you put it here, it applies to the whole controller
public class HomeController : Controller
{
[CustomAuthentication]//<-- Here it only applies to the Index action
public ActionResult Index()
{
return View();
}
}
I believe what you are looking for is a custom ActionFilter. Code in an ActionFilter can be executed before the ActionResult, allowing you to redirect anyone without the UserId session.
Instead of putting code in every ActionResult you would do something like this
[MyCustomActionFilter]
public ActionResult Index()
{
return View();
}
Here is a tutorial on how to create one Custom Action filters in MVC
I've got a rather large MVC web application and I am repeating an action in each controller to see if a customer has completed the application process (in which case a flag is set on their profile which I check against). Ideally I want to remove this code from each action method and have it applied to all action methods which return an action result.
You could make a custom attribute that handles this for you, you could have the attribute at the Controller level or ActionResult level.
[CompletedApplication("User")]
public ActionResult YourAction
{
return View();
}
public class CompletedApplicationAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// Your logic here
return true;
}
}
If all expected controller inherited from some BaseController than using that, common behavior can be set.
public class HomeController : BaseController
{
}
and BaseContoller will be like
public class BaseController : Controller
{
protected BaseController(common DI)
{
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// some logic after action method get executed
base.OnActionExecuted(filterContext);
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// some login before any action method get executed
string actionName = filterContext.RouteData.Values["action"].ToString(); // Index.en-US
filterContext.Controller.ViewBag.SomeFlage= true;
}
// If Project is in MVC 4 - AsyncContoller support,
//below method is called before any action method get called, Action Invoker
protected override IActionInvoker CreateActionInvoker()
{
return base.CreateActionInvoker();
}
}
I have a pretty simple requirement.
If the user goes to http://www.somedomain.com/ and is not logged, I want MVC to route user to HomeController.
If the user goes to http://www.somedomain.com/ and is logged in, I want MVC to route user to ClientController.
Is there an easy solution for this problem?
Thank You very much!
In your HomeController, Index action, redirect to the ClientController if the HttpContext.User is not null:
public class HomeController : Controller
{
public ActionResult Index()
{
if (HttpContext.User != null)
{
RedirectToAction("Index", "Client");
}
}
}
EDIT: Or Use Request.IsAuthenticated
public class HomeController : Controller
{
public ActionResult Index()
{
if (Request.IsAuthenticated)
{
RedirectToAction("Index", "Client");
}
}
}
There are quite a few ways to solve this.
Depending on your requirements you could implement an IAuthorizationFilter for this purpose and implement the OnAuthorization method something like this.
public void OnAuthorization(AuthorizationContext filterContext)
{
IUser user = _currentUserProvider.CurrentUser;
if (user != null)
{
// you can perform perform additional user-authorization here...
if(_authorizationService.IsAuthorized(user))
{
//user is authorized
return;
}
else
{
HandleUnAuthorizedRequest(filterContext);
return;
}
}
//user is not authenticated (not logged in)
HandleUnAuthenticatedRequest(filterContext);
}
You then use the actionFilter on your controller method or controller class.
See http://msdn.microsoft.com/en-us/library/dd410209(v=VS.90).aspx for more information about Action Filters.
Now, if you want all unauthenticated requests to go to the ClientController, you can handle the AuthenticateRequest event in your HttpApplication (usually global.asax.cs) class and implement something like in the actionFilter above.