How to get caller IP addres in ASP.NET MVC4 Global.asax.cs Application_Start event ?
HttpContext.Current.Request object is not available there.
Thread.CurrentPrincipal.Identity exists.
I want to log user name and IP address which were used to start application.
MVC4 application runs in Windows and in Mono
As you can see by the ASP.NET Lifecycle on MSDN, the Application_Start event not only happens long before the AcquireRequestState event where the request object is built, it is also done out of band with the request lifecycle altogether. In other words, Application_Start occurs only once when the application starts or when the application pool recycles, not once per request.
So, the answer to your question is simply that you can't do that (unless of course you set a static variable in the Application_Start event and use either Application_BeginRequest as in Darin's answer or an MVC filter to actually do the logging).
But MVC includes authorization filters and action filters which are meant for implementing cross-cutting concerns such as logging and/or auditing of the current user's IP address. Authorization and action filters do not run until after the request object has been created.
The HttpContext is not available when the application starts. You could achieve that in the BeginRequest method in your global.asax:
private static bool initialized = false;
private static object syncRoot = new object();
protected void Application_BeginRequest()
{
if (!initialized)
{
lock (syncRoot)
{
if (!initialized)
{
// do your stuff with the user IP getting from the current context
initialized = true;
}
}
}
}
Related
In my MVC project, there are multiple actions where security between requests and responses is increased with the [ValidateAntiForgeryToken] attribute. This works fine. Problems arise when a user keeps the page open for several minutes (I assume 20, (Session State timeout?)) and then sends a request to the server. This causes an error, because the token sent back no longer matches the token on the server.
Reading this question, it can be solved by adding a HandleError attribute on each specific action that uses [ValidateAntiForgeryToken].
Is there a way to set this globally for the entire website? I'd hate setting it on every action separately.
You can regsiter an ActionFilter globally in global.asax on Application_Start() event.
protected void Application_Start()
{
// Register global filter
GlobalFilters.Filters.Add(new HandleErrorAttribute());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
I have a com dll built in .net and referred it as a interop.mycomlib.dll in my ASP.NET application. I initialize a class in the com object then call some functions and finally when the user signs off or closes the browser I release the com object.
Below is the code I am using. Initially, for the first user, the InitInstance() is called but when the user signs off the ExitInstance() of the com is not called.
If any other user signs on the InitInstance() is not called again because the same instance of com object is used for all the users. ExitInstance() is called only when an iisreset is performed or the w3wp process is terminated.
Is this the default behavior of how com interop works with asp.net, or is there something I am missing to do to completely dispose the com object?
public class ComFacade : IDisposable
{
public ComFacade()
{
myComObj_ = new MyCOMLib.MyClientClass();
}
..............................
public void Dispose()
{
Dispose(true);
myComObj_ = null;
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
try
{
Marshal.ReleaseComObject(myComObj_);
}
catch (Exception ex)
{
throw;
}
}
this.disposed = true;
}
}
}
Thanks
You don't mention what the scope of the variable containing the ComFacade instance is. If the variable is static then this would be the behavior I would expect.
I would suggest you understand the ASP.NET page lifecyle and the implications of that with variables of different scopes. Unless the COM reference is supposed to be a singleton then you will need to create a new instance each time the page loads and dispose of it as appropriate (probably when the page is rendered).
Update (based on comment)
Note: This answer applies to any object in .NET that you try to keep around longer that a single page request. Eventually all objects are disposed / garbage collected.
You mention that the object is created when the user logs in and disposed when they log off. The only way you could do this is to cache the object in something static to keep reference to it. Keep in mind that every time the user does something in their browser a request goes from the browser back to IIS/ASP.NET for processing and invokes a page life-cycle (over-simplification, but good enough). Each time the user does this the page may be handled by a different thread in the App Pool each time. If more than one user is interacting with the site then over a period of time the same thread may (and most likely will) get used by more than one user. In short this is why with ASP.NET/IIS you must be extremely cautious with using singletons / static members.
On a side note, my question would be why do you need a reference to the COM object for more than a single page request?
I am trying to customize a vended product that routes all requests through a HttpHandler. The handler analyzes the request to figure out what page to route the user to and performs a Server.Transfer(). Unfortunately, I need to access SessionState on a page and the handler doesn't implement IRequiresSessionState and is marked as internal so I can't inherit from it. After a lot of googling the best solution I found was to create an HttpModule that changes the handler that processes the request at different points in the request lifecycle. On PostMapRequestHandler I would change the handler that processes the request to my own that implements IRequiresSessionState and PostAcquireRequestState I would map it back.
This works but does anyone have a better solution?
I figured out a more elegant way to enable session state. You can override the session state behavior of a handler. I created a module that forces session state.
public class SessionEnablerModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PostMapRequestHandler += new EventHandler(context_PostMapRequestHandler);
}
void context_PostMapRequestHandler(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
if ((app.Context.Handler.GetType().ToString().Equals("Handler I want to enable session state for")))
{
//enable session state
app.Context.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
}
Another solution could be to route all request through your handler that requires session state and then pass those requests to internal handler by invoking its ProcessRequest method - you can create the instance of internal handler by using say Reflection (or using handler factory if any).
However, using HttpModule to swap handlers is definitely a better solution. Because you can choose to swap the handler selectively by looking at the requested URL. That way, you may not have to load/save session state for all requests (that can be expensive operation for out-of-proc sessions)
please tell me why IHttpHandler need to implement IRequiresSessionState. without implementing it we can not read/write anything in session variable?
can't we access directly HttpContext.Current.session like this way.
please explain.......thanks
public class MyHttpHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
var MyValue = context.Session["MyKey"] as String;
MyValue = "Hello World";
context.Session["MyKey"] = MyValue;
}
public bool IsReusable
{
get { return true; }
}
}
The session state is not a native part of the HTTP infrastructure. This means that the request will need to serialize/load the session information (either from memory or database or another server) for requests that need access to session and save it back when done.
HttpHandler is a the process (frequently referred to as the "endpoint") that runs in response to a request made to ASP.NET http runtime. It is used to handle a particular type of object/class/resource as you define it. If processing of that resource does not need access to session, that particular request does not need to go through the loading/saving of session data unnecessarily. So, by default, session is not available for HTTPhandlers, unless it is a predefined handler like Page handler.
To successfully resolve any call to the Session object, the runtime environment must add the session state to the call context of the request being processed, which is IRequireSessionState in this case.
Check out this msdn link for more details.
To answer your question, no, if you dont implement the IRequireSessionState, you will not have access to the session objects in your handler class due to the above mentioned facts.
If you do not implement this interface you should not be able to successfully use the session object. You are supposed to use this interface if you want access to the session, regardless of how you access it.
It shouldn't work without it. If it does, its a fluke and don't rely on it.
The ASP.NET SessionStateModule will not populate the context's session properties unless the handler is marked with the IRequiresSessionState interface.
I'm working on an app using ASP.Net's form authentication. The client also makes RESTfull calls to the server (ExtJS components on front end).
We are using a custom HttpHandler for the service calls.
My problem is that anytime the anytime the authentication cookie expires my HttpHandler 's ProcessRequest method isn't called in order for me to check for the cookie's absence and redirect the user to log in again.
An example would be a user leaves a page open then comes back in 20 mins and clicks on a dropdown that is loaded asynchronously. The app just hangs never getting to my handler.
Any thoughts?
Highly suggest reading the section entitled "The Pipeline Event Model" in this MSDN magazine article: Securely Implement Request Processing, Filtering, and Content Redirection with HTTP Pipelines in ASP.NET.
In a nutshell, authentication is performed well before the request is handed over to ProcessRequest() in your HttpHandler. If you need to handle these cases, you will need to hook into the pipeline events (such as BeginRequest or Authenticate Request) and add your own handlers, like so:
public class EnableWebServicesModule :
IHttpModule
{
public void Init(HttpApplication app)
{
// register event handler
app.BeginRequest += new EventHandler(this.OnBeginRequest);
}
public void OnBeginRequest(object obj, EventArgs ea)
{
// Check if security works here by looking for the cookie or
// the user context.
}
...
}
For further reading on this fascinating and exciting topic, check Rich Strahl's walkthrough: A low-level Look at the ASP.NET Architecture