When I invoke a controller, it's possible that the view response calls other controllers. Is there a way to determine, in MVC, all of the views and/or controllers were called in a single response?
Thanks.
I don't think that the framework exposes this directly, but you could hook into the OnActionExecuted method and log each action that gets invoked along with a unique request identifier. You could hook into Application_BeginRequest in global.asax.cs to generate a GUID to use as the unique id for that request (stored in the Session, but overwritten for each new request). If you use a base controller and derive all your controllers from it, you could put the logging in the base controllers OnActionExecuted method to keep it DRY.
Alternatively, you could look at creating a custom ActionInvoker and put the logging there.
This is where I would start anyway, though, there might be a better way.
NOTE: This will only tie together actions that are invoked server-side for the request. Any AJAX requests kicked off client-side when client receives the rendered view will show up as different requests. If you need to include those as well, your unique id generation code should probably only run on non-AJAX requests, leaving the existing id alone in the session otherwise. Typically AJAX requests have an HTTP_X_Requested_With header to distinguish them.
Related
I need to check some stuff (Cookies) for each request coming to my application.
In ASP.NET we've used HttpModule for this task , the question what should be used in MVC ? Some Global Filter , or I can Use HttpModuler as well, is there Any difference in Request PipeLine between MVC and regular ASP.NET ?
MVC is an abstraction over ASP.NET and therefore their "hooks" really depend at which level you want to inject your logic. An action filter will allow you to hook into MVC specific events:
OnActionExecuting – This method is called before a controller action is executed.
OnActionExecuted – This method is called after a controller action is executed.
OnResultExecuting – This method is called before a controller action result is executed.
OnResultExecuted – This method is called after a controller action result is executed.
Whereas an HttpModule only allows you to hook into ASP.NET (upon which MVC is built) specific events:
BeginRequest - Request has been started. If you need to do something at the beginning of a request (for example, display advertisement banners at the top of each page), synchronize this event.
AuthenticateRequest - If you want to plug in your own custom authentication scheme (for example, look up a user against a database to validate the password), build a module that synchronizes this event and authenticates the user in a way that you want to.
AuthorizeRequest - This event is used internally to implement authorization mechanisms (for example, to store your access control lists (ACLs) in a database rather than in the file system). Although you can override this event, there are not many good reasons to do so.
PreRequestHandlerExecute - This event occurs before the HTTP handler is executed.
PostRequestHandlerExecute - This event occurs after the HTTP handler is executed.
EndRequest - Request has been completed. You may want to build a debugging module that gathers information throughout the request and then writes the information to the page.
So it really depends on when you need to hook in your event and which events you need.
If the HttpModule worked well for you before then it will continue to with Mvc.
The other parts of your question are quite broad in scope and think you'd be as well reading a good article on asp.net-mvc pipeline and extensibility.
I've done similar things using a global action filter. It works quite well, and keeps your code integrated within your application.
An HTTP module works as well, of course, but this will mean seperating the code from your main application and maintaining it seperately. Unless your code spans multiple sites or is used in multiple applications, or needs to work with web forms sites, then I would use a global filter.
I've an application which has some controller's actions calling slow 3rd party web services. These actions are called using AJAX calls from the page.
I can use async controllers to free ASP.NET thread pool, that's great. But what about session? If I use InProc session and a request made to "slow action" the particular user can't make any request to the application because his session is locked by first "slow" call.
In PHP there is a method session_write_close() which I can use as following:
Accept user's request to slow action
Check rights of the user to access controller/action based on session data
Write something to the session if needed
Call session_write_close(). From this point session is closed by this request and any other request from the same user can access it
Make my slow call (maybe in some async way)
I know that I can disable session state on the controller level using [SessionState] attribute, but that's not the solution.
Any ideas?
I think it could be several scenarios.
1) make changes in controller factory and change it to produce contorllers without session or with some custome session implementation
2) try to read this article about sessionless controllers
I have many webmethods in one asmx. I need to perform licence checking before some of this webmethods invoked. I can insert following code to each web method that needs checking:
if (!AllRight())
{
// badRequest
return;
}
Or I can insert complex filter to HttpModule to detect webmethod by URL.
I need something like attribute for webmethod and place where I can handle it.
Is there pretty good solution?
IMO, both of these options are good. Using HttpModule is a good approach - detecting web service call by parsing url is really simple - in short, you are looking for particular asmx (and handling WSDL request). If you want to do selective license check then do simple method name sniffing in URL (as opposed to decorating methods with attribute).
Apart from above options, you have couple of alternatives
Uses some Aspect Oriented Programming frameworks (for example, PostSharp) to inject license checking code by using attribute to decorate the method.
Do it at handler level. Essentially, implement a IHttpHandlerFactory and use it for your asmx end points. The implementation will wrap WebServiceHandlerFactory (or ScriptHandlerFactory in ajax cases) and will return a handler that wraps over the handler object provided by underlying handler. But frankly, this is a brittle solution and essentially same as HttpModule but more complicated.
I am working on a mixed situation where i am using Servlets & Struts2.
I am calling a HTTPServlet and where i am processing on data.
Then I need to make a call to struts API to insert data in DB.
In that i am using HTTPSession also.
So I am calling
ServletActionContext.getRequest()
To get HttpRequest and then session in that struts action class.
Struts Action class is getting called by Servlet.
But
ServletActionContext.getRequest()
always returns NULL.
Is it because that it is not getting called by web.
First, ServletActionContext and ActionContext both use a ThreadLocal to store per-request objects (such as the request and response). This is handled by Struts2. If you attempt to call those from a Servlet, they'll return null, since the request was routed to your servlet, not to Struts2 (and thus Struts2 did not create an action context for the request).
With that said, Struts2 is a higher level abstraction over the Servlet API. The fact that you are invoking a Struts2 action from within a servlet sounds really wrong.
If you need to perform some common process in both a servlet and an action, then create a separate class to handle the process (i.e., inserting data in a database) and then call that class from both your servlet and your action.
If that isn't what you're trying to do, then please provide more details, along with an example of your servlet and action code.
From an HTTP module, is there a way to persist something in the Request to be accessed by a mater module or the eventual handler? Can you "stick" something on the Request as it passes through that will still be there later in the pipeline?
You can use the HttpContext (the one exposed by the static Current property). It has an Items property which is meant to be used specifically to shuttle data between modules and handlers, as indicated by the documentation:
Gets a key/value collection that can
be used to organize and share data
between an IHttpModule interface and
an IHttpHandler interface during an
HTTP request.
Which can be located here:
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.items.aspx