ActionContext.getContext() returns null using Session in Struts 2 - struts2

I am trying to use Session in Struts 2:
private Map<String, Object> session = ActionContext.getContext().getSession();
But I'm getting this error:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke
"com.opensymphony.xwork2.ActionContext.getSession()" because the return value of
"com.opensymphony.xwork2.ActionContext.getContext()" is null
I tried to use SessionMap of Struts but still got the same error message. I have tried changing the struts-core libraries and also tried a few solutions from Google but still doesn't solve this issue.

ActionContext is a container placeholder for the action invocation, more detailed explanation is here.
There's a lot of reasons when an action context could be null. You are starting another thread, or modify existing one, or it's just not created yet.
To get a SessionMap there's another approach. Let your action class to implement SessionAware and make sure you have configured a default interceptor stack for the action. After that the session map should be injected to the action instance. More about it here.

Related

How do I call a specific Controller Action to test code within it, especially session variables?

I am using MVC5 on ASP.NET 4.5
I want to debug specific Controller Actions without running the whole application where I would need to know how to navigate to the specific Action, in addition to it taking much time, since I have much code to refactor and test.
I have considered Unit Tests, but using the debugger seems more appropriate for what I am doing.
Also I have session variables within the Action Code.
The closest I have come to a solution is to have a wrapper Action in Home ie:
public ActionResult Tx()
{
return new MyApp.Areas.Area1.Controllers.OrderController().Index();
}
I would then copy and paste the relevant Namespace, Controller and Action with any relevant parms into the "Tx" Action.
This does invoke the relevant Action without me needing to navigate to the specific Action. I just call Home/Tx. However I am getting null exception errors with my Session variable code:
Session["OrderID"]=null
Debugging the Action, with the Session variables works fine when I navigate directly from the application. When I use Home/Tx it is still on the Dev Web Server and within the Debug process, but perhaps I am in a new context as another Action is creating the Controller.
1) Any idea why my idea does not work with Session variables?
2) If anybody has a better idea on how to invoke specific Controller Actions then I would appreciate that.
Thanks.
You need to call the Initialize method on your controller before using it. Try something like:
var httpContext = new HttpContextWrapper(HttpContext.Current);
var routeData = RouteTable.Routes.GetRouteData(httpContext);
var controller = new MyApp.Areas.Area1.Controllers.OrderController();
controller.Initialize(new RequestContext(httpContext, routeData));
return controller.Index();

File Dependency Caching in MVC3

I am trying to implement file dependency caching in mvc3. As I am new to MVC, I browsed searched google but I didn't get any help.
Can any of our guys help me out? or what is the work around for this?
I tried same as what we do in asp.net but I get error.
Code I tried:
public ActionResult About()
{
Cache.Insert("DropDownData", "", new System.Web.Caching.CacheDependency(Server.MapPath("~/testxml.xml")));
return View();
}
Error That i got:
An object reference is required for the non-static field, method, or property 'System.Web.Caching.Cache.Insert(string, object, System.Web.Caching.CacheDependency)
Your problem is that you are calling the instance method Cache.Insert without a reference to an instance of the cache. ASP.NET MVC does not expose the default Cache in the Controller by Default.
In order to access it from the controller, you need to use HttpContext.Cache.Insert
That being said, this kind of behavior is more appropriately localized in an ActionFilter. Check out the following for more on this: http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/improving-performance-with-output-caching-cs
Try
System.Web.HttpRuntime.Cache.Insert
System.Web.HttpRuntime.Cache is the cache instance of your current application.
Have you added reference correctly ?
Try to make an object likewise
CacheDependency CDep = new CacheDependency(fileName /*your file path*/, dt /*Set Start parameter to current date */);
and then use insert as
cache.Insert("DropDownData", "", CDep);

Use a IRouteConstraint or ActionFilterAttribute when validating session data against route data

I've been implementing a RouteConstraint recently whos responsibility is to Match a custom route value against some model data that is in the session.
What I've found is that the session is null for the routeDirection of IncomingRequest.
Is the session not configured until
the controller is
created/initialized?
If this is the case, is this type of
function better suited to a filter
applied at the controller level?
Are there any other viable options?
The shame of it is that this validation does need to be applied on every route except for when the session is configured on first entry, so I thought a route constraint would be the best solution.
Thanks.
Since it has to happen on pretty much each call I would probably handle the controller's (or base controller's) OnActionExecuting and then set the ActionExecutingContext.Result to return a new RedirectToRouteResult with a RouteValueDictionary that contains the values you need. This could be encapsulated in an ActionFilter as well (controller implements IActionFilter).
It is not clear to me what exactly you are trying to implement (redirection to login page or rendering some message) so I can't give any good alternative solution but I can tell you that session is not accessible when IRouteConstraint is being evaluated because routing pipeline happens before session is loaded. E.g. routing might render page that doesn't require session at all.

Custom Controller Factory, Dependency Injection / Structuremap problems with ASP.NET MVC

I recently tried to implement dependency injection using StructureMap. I managed to follow the example all the way but I'm encountering a thrown exception every time I try to run the application. Here's some code snippets from my controller factory.
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(Type controllerType)
{
if (controllerType == null)
throw new ArgumentNullException("controllerType");
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
My Global.asax calls a static BootStrapper class which registers all my dependencies but it looks like the StructureMapControllerFactory's GetControllerInstance is getting called twice. The first time it's called, a proper controllerType is passed in but it's always null on the second calling.
The first time GetControllerInstance is called, the type is set to HomeController which is correct. The code the fires in HomeController and it returns the View(). On the return of the View(), the Page_Load event is called on the aspx file. After stepping through that, it arrives at a line:
httpHandler.ProcessRequest(HttpContext.Current);
That's where the GetControllerInstance is called the second time.
Here's my Global.asax bits which may be relevant:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
Bootstrapper.ConfigureStructureMap();
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
I'm very keen to get dependency injection working and would be most appreciative if anyone can help me out. :)
UPDATE
The reason this is happening is that when an image is specified in a css file, and that image is missing the routing framework tries to map the url to a controller. Ignoring the routes as listed below will prevent the error from happening, but I decided not to implement it because it's a nice way of being notified that you have a missing resource.
You can see a detailed explanation along with examples of setting up dependency injection using Structure Map here.
I was having the same issue and I think I figured it out. For whatever reason whenever you try to provide your own Controller Factory you need to add a couple of additional IgnoreRoute definitions. The first thing I would do is add this line to your GetControllerInstance method:
if(controllerType == null)
return base.GetControllerInstance(controllerType)
This will at least give you more information in the error message as to what the request is that is causing the controllerType to be null. In my particular case I had a background image in my css file set like this:
background: url(img/logo.gif);
So what happens is the routing is looking for a controller called "img" and an action that takes logo.gif or something along those lines. That's obviously not the correct behavior.
After some digging I realized I needed to add an IgnoreRoute definition to my Global.asax file that would ignore anything in the "content" directory of my site like this:
routes.IgnoreRoute("{Content}/{*pathInfo}");
I'm still not sure why you don't need to do this with the default ControllerFactory, but nonetheless it works.
You'll probably run into the same issue with favicon.ico. Particularly if you using google crhome. You'll need to add this as well:
routes.IgnoreRoute("{*favicon}", new {favicon=#"(.*/)?favicon.ico(/.*)?"})
I am guessing you are requesting a static file, such as a javascript file, that has not been added to your project or perhaps the reference to it has a typo. You should monitor your browsers web requests and look for web requests for that do not correctly resolve to a static file when they should. You can use firebug in FF or fiddler if you are using IE to do this.

Asp.Net MVC Beta: Previous RouteData overrides current RouteData?

I have something similar to the following method:
public ActionResult Details(int id)
{
var viewData = new DetailsViewData
{
Booth = BoothRepository.Find(id),
Category = ItemType.HotBuy
};
return View(viewData);
}
and the following Route:
routes.MapRoute("shows","shows/{controller}/{action}/{id}", new {id = 0});
Everything worked fine before the Beta, when I had Preview 3. Now the method will fill the id correctly the first time I execute the action. However the second time the controller's ModelState contains the last-use id value. This causes the ActionInvoker to use it in the method's parameter instead of the Route value.
So if I call the action twice on two different entities the results are such:
www.mysite.com/shows/Booth/Details/1 => Details(1)
www.mysite.com/shows/Booth/Details/2 => Details(1) //from ModelState["id"]
From my quick scan with Reflector it seems it first binds parameters to the ModelState then to Routes. However, I never even posted anything from the model. As far as I can tell the ModelState should not contain anything.
Is this a bug in the Beta, possibly a bug somewhere in my code, or is there some design feature that I am ignorant of? Any insight into the nature of ModelState and why this happens is appreciated.
EDIT:
I discovered that this issue is actually a symptom of what appears to be a bug with the DefaultValueProvider if you instantiate a Controller from an IoC container that exists for the lifetime of the Asp.Net application.What happens is that the DefaultValueProvider uses the first ControllerContext given to the Controller and never updates it until the controller is recreated. This causes old RouteData to be used for method parameters instead of the current RouteData.
It's hard for me to tell what you expect to happen and what is happening from your post. Is it possible there's an error in your BoothRepository.Find method such that it returns the same thing every time?
ModelBinder should not be affecting this method because the parameter to the action method is a simple type, int.
Were both of these requests GET requests? If you still are having problems, can you try and create the simplest repro possible and email it to philha - microsoft dot com?
EDIT: The problem ended up being that the developer was attempting to re-use the valueprovider across requests (by having Castle Windsor manage the lifecycle of Controllers). Right now, there's no support for re-using controller instances across requests like you would with IHttpHandler which has a IsReusable property. So in general, reusing controllers across requests requires doing a lot more work on your end. :)
The problem is the LifeStyle, I completetly overlooked the fact it was being defined, which means by default the controllers will use the Singleton lifestyle. Setting the LifeStyle to Transient for all controllers will sort this problem.
if you use spring.net modify
Controller's singleton to "false"
This is a common issue when using Singleton behavior with a IoC container such as Spring.NET or Windsor. Controllers should not have singleton behavior because the ControllerContext is per request, much like HttpContext.

Resources