I have read that an effective way to use enable session in web api 2 is like so:
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
}
I have also created a class that inherits from AuthorizationFilterAttribute and overrides the OnAuthorization method.
But this event is never called - what am I doing wrong?
You could try creating a HttpModule:
public class WebApiSessionModule : IHttpModule
{
protected virtual void OnPostAuthorizeRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (this.IsWebApiRequest(context))
{
context.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
}
}
}
You'll need to add this to your web.config in
<system.web>
<httpModules>
Related
I am trying to retrieve some data from db and store it some Session variable in order to have it in _Layout.cshtml on all pages, no matter what page the user will access from the start.
Global.asax:
protected void Application_Start()
{
...
Manager mng = new Manager();
HttpContext.Current.Session["company-cellphone"] = mng.GetContacts().CompanyCellphone;
}
Error: Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
you are trying to access the session from Application_Start but there is no live Session yet.
session is not available in all events of global.asax
as a workaround try this:
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
HttpContext context = HttpContext.Current;
...
Manager mng = new Manager();
HttpContext.Current.Session["company-cellphone"] = mng.GetContacts().CompanyCellphone;
}
}
I'm not sure about your requirement but I would recommend to access the session in controller.initialize method
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
//// access session here
requestContext.HttpContext.Session["company-cellphone"]=mng.GetContacts().CompanyCellphone;
}
Application_Start runs before any sessions can be created. And a session is specific to a single client connecting to your application.
You can create a static class and store the company-cellphone value in it.
In your Models folder create a new class file named Global.cs in that file create a static class with properties that will hold your application level information.
public static class Global
{
static string companyCellPhone;
public static string companyCellPhone
{
get
{
return this.companyCellPhone;
}
set
{
this.companyCellPhone= value;
}
}
Then your Application_Start method would look something like this:
protected void Application_Start()
{
...
Manager mng = new Manager();
Global.companyCellPhone = mng.GetContacts().CompanyCellphone;
}
I'm going to go out on a limb and guess that this is a single global value to be viewed by all users. In that case you could store the value in HttpApplicationState rather than HttpSessionState:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
Application["YourValue"] = "SomeValue";
}
}
I'm not necessarily advocating its use. But just as Session can store user-specific values, Application stores values that are global to the application.
This might sound like a stupid question, but I am about to implement a custom security database and framework for a new site. I was wondering how best to handle this.
NOTE: I am NOT using the ASP.NET Membership for this, I am using a custom database and everything custom for user management.
There will be several levels of security, so I am a bit stumped on this without making it too difficult. The only thing I could think of so far is check on EVERY PAGE in the Page_Load if they have the right security:
protected void Page_Load(object sender, EventArgs e)
{
CustomUser user = Session["User"] as CustomUser;
if(user != null && user.CanAccessFeature("TopicModeration"))
{
//initialize page elements
}
else
{
Response.Redirect("Default.aspx?featureDenied=TopicModeration", false);
Context.ApplicationInstance.CompleteRequest();
}
}
That works fine, but if I have dozens of pages that have different restrictions, it can get a bit repetitive. Does anybody have any thoughts on this? Should I inherit from System.Web.Page for each security feature, and use that on the page instead?
Thanks!
May i suggest the following approach:
Create a custom controller class as such:
public class CustomController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
CustomUser user = Session["User"] as CustomUser;
if(user != null && user.CanAccessFeature("TopicModeration"))
{
base.OnActionExecuting(filterContext);
}
else
{
filterContext.Result = new RedirectResult("Default.aspx?featureDenied=TopicModeration", false);
Context.ApplicationInstance.CompleteRequest();
}
}
}
Then you may have your controllers where you want that check to inherit from this controller.
You can create a Base Class and make all master pages (or pages) inherit that class.
Here is an example when a Master Page inherits a class.
Class for all master pages to inherit.
public class PageBase: System.Web.UI.MasterPage
{
protected override void OnLoad(EventArgs e)
{
//Put your security code here...
base.OnLoad(e);
}
}
Here is a Master page inheriting the class above.
public partial class Site1ColMaster : MySite.PageBase
{
protected void Page_Load(object sender, EventArgs e)
{
//Master page
}
}
i need to hit DB and load the settings file before every page loads. Am currently using MVC and am creating that call in constructor in All controllers.
Am not sure of what is the better way to handle this scenario ?? I read like we can use singleton class in this scenario.
Is it possible to have the data once and reuse across pages ? What is the best way ?
Some sample code snippets will help !
Option one: you can used Application_BeginRequest in Global.asax.cs:
protected void Application_BeginRequest(object sender, System.EventArgs e)
{
//something
}
Option two: create a global filter:
public class ActionLogFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
// do your stuff. This is run before control is passed to controller
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// do stuff here - control here is passed after controller is done with the action execution
}
}
and then add controller to execution stack in Global.asax.cs:
FilterConfig.RegisterGlobalFilters(GlobalFilterCollection filters)
and FilterConfig is usually looks like this:
public static class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyFilter());
}
}
Option three: Create your global controller that overrides OnActionExecuting (see the filter example). Make your controllers to inherit from that global base controller.
I prefer option with filters. Favour composition over inheritance
Is there an equivalent for MVC.NET's OnActionExecuting in standard asp.NET? ?
I thought it would be Page_Load since OnActionExecuting would be called each time an action is executed (or the page loads). But I'm running into inheritance issues when I try to use Page_Load instead.
Since it is very difficult to make my solution work with a Page_Load I'm thinking I might not have the best ... solution.
Any thoughts on whether they are equivalent or close enough?
Background:
I'm converting a piece of an MVC3 application into a standard .NET to wrap in a SharePoint Web Part.
Here's the MVC code I'm trying to translate, as you can see its the user security bits I'm translating:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!SiteCacheProvider.ItemCached(enmCacheKey.SiteSetting)) {
if (filterContext.IsImplementedGeneralPrincipal()) {
IUserProfile userProfile = ((IGeneralPrincipal)filterContext.HttpContext.User).UserProfile;
SiteCacheProvider.ChangeSiteSetting(userProfile.SiteID);
}
}
base.OnActionExecuting(filterContext);
}
First, take on account that no Actions are in ASP.NET because the model is different (Event-Based) - There're no methods(actions) which you can decorate with Action Filters, it's all about the Page-Cycle events.
Second, In ASP.NET, you may use HTTP modules (HttpApplication.BeginRequest particularly) in order to intercept incoming requests to your application pages by adding your required logic.
From MSDN:
HTTP Modules use to intercept HTTP requests for modifying or utilize
HTTP based requests according to needs like authentication,
authorization, session/state management, logging, modifying Response,
URL rewriting, Error handling, Caching....
For example:
using System;
using System.Web;
using System.Collections;
public class HelloWorldModule : IHttpModule
{
public string ModuleName
{
get { return "HelloWorldModule"; }
}
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<h1>HelloWorldModule: Beginning of Request</h1><hr>");
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<hr><h1>HelloWorldModule: End of Request</h1>");
}
public void Dispose()
{
}
}
In my project (c#), we have an HttpModule that creates a custom Principal that we attach to the CurrentPrincipal.
This is working in all of our MVC3 apps and in our classic ASP.Net apps.
We have an AuthorizeAttribute override we use to secure our Controller methods - seems pretty standard.
The problem is that in the custom authorizeAttribute, the user (httpContext.User) is a RolePrincipal and not the custom principal.
To troubleshoot, I put some handlers in my global.asax to trap beginrequest() and endrequest(). Well, in BeginRequest my User is what we expect - the custom principal. In EndRequest, the user is a RolePrincipal again. The web.config declarations of the HttpModule are good - I can step thru the HttpModule's code.
Does anyone know what's going on? We have a custom HttpModule, but I can't modify that code for this project (it's being used everywhere and it works fine).
This is my first MVC4 project - I'm wondering if MVC4 does something differently.
Code below. Is there any info I've left out?
edit: added authorizationattribute code.
Code
(In HttpModule)
private void BeginRequest(object Sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
var Id = new TASBIdentity();
context.User = new TASBPrincipal(Id);
Thread.CurrentPrincipal = context.User;
(etc...)
(In global.asax)
void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
var user = context.User; // user is correct type
}
void Application_EndRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
var user = context.User; // user is default type (not correct)
}
(In the authorizeattribute)
public class SecuredByFunctionAttribute : AuthorizeAttribute
{
private readonly string _functionKey;
public SecuredByFunctionAttribute(string functionKey)
{
_functionKey = functionKey;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
return httpContext.User.IsInRole(_functionKey);
}