Should I get the session through SessionAware or ActionContext? - struts2

After reading the differences between obtaining the session map via ActionContext.getContext().getSession() and having it injected through
SessionAware I was wondering which is the preferred method, and why?
The API recomends to use SessionAware, and I read on the web that using SessionAware makes the application easier to test--is testing the only issue?
Can someone elaborate a little bit on this subject or point out to references explaining this?

I have already replied the same in your earlier question.you can use either way or even can get access to the Session by more ways.
one way
Map attibutes = ActionContext.getContext().getSession();
But if you use this and your action class is directly tied to the ActionContext which is Struts2 specific way.
One of the prime goal of Struts2 is to decouple Action classes from underlying HTTP context as well with other direct dependencies.
Also writing test cases for plain POJO is way easy and better than the other way.
By implementing SessionAware interface you are indicating Struts2 that you want session as a simple map object, this not only making code much decoupled but easy to maintain and test.
I hope some one else will come with more good points on this

SessionAware is a dependency injection approach, whereas ActionContext.getContext().getSession() is not. Otherwise, they are identical. Both of these approaches return you a Map<String, Object> as opposed to the HttpSession which is part of the servlet API.

Related

How far to go with IoC

I was wondering how far I should take my IoC implementation in terms of loosely coupling my application. I am using constructor injection in my MVC controller but wondered if I should also be resolving all my other dependencies in the controller instead of newing up objects. For example if I was to create a new User object within a controller method would I use?
var user = new User();
var user = myContainer.Resolve<IUser>();
I like the idea of breaking my dependency on User but is that going too far and could possible make my code harder to read?
This is a very good question, when you read and hear about DI it makes sense and this is the next natural conclusion.
First Steven's point is correct you should not pass the container around. If you need to construct IUser on the fly and it needs to be abstract you should rather inject an Abstract Factory.
Sebastian also posted a good link.
I actually wrote about this in an answer I posted here.
The bottom section of the post:
Not every object and dependency needs or should be dependency injected, first consider if what you are using is actually considered a dependency:
What are dependencies?
Application Configuration
System Resources (Clock)
Third Party Libraries
Database
WCF/Network Services
External Systems (File/Email)
Any of the above objects or collaborators can be out of your control and cause side effects and difference in behavior and make it hard to test. These are the times to consider an Abstraction (Class/Interface) and use DI.
What are not dependencies, doesn't really need DI?
List
MemoryStream
Strings/Primitives
Leaf Objects/Dto's
So in your particular case it really depends on what happens when IUser is constructed also whether you actually need to substitute it with different implementations. If this is not the case and User has only simple types with no external dependencies or side effects just new it up.
Consider what happens when you call new User(), look at the graph below, if it causes other objects to be created and looks like something in the graph below consider IoC.
A cascading dependency object graph:
In this example new on the object either requires or creates a whole bunch of other dependencies. It is most likely out of your control what those dependencies are or do.
When your object is a simple dto it doesn't suffer this problem and IoC is likely not so much required.

MVC, not "supposed" to use HttpContext.Current anymore?

Someone in a post here, commented that you should not use HttpContext.Current when using MVC, rather, you should be using ControllerBase.ControllerContext. In some respects, this makes sense, but in other respects it doesn't.
For example, ControllerContext is an instance variable, so everywhere I want to reference, say, my Session variables, I need to have a reference to the Controller? Why are we "not supposed" to be using HttpContext.Current in MVC, when you still can? Is there an "appropriate" MVC "way" to get at my Session object without having to have a reference to the Controller?
I know test-wise, it is better for reasons stated in many other places, but I am working on a project that manages Session variables and references HttpContext.Current and I want to know if there is a better way to get my hands on the Session object without passing a reference to the controller.
This is mainly since unit testing would be very difficult if you use HttpContext.Current since mocking this value is not possible using normal mock frameworks.
HttpContext.Current also makes for more brittle code since it can be abused and misused. For example, you can use it in business layer since it is convenient but it will break if you choose to use an alternative presentation layer other than ASP.NET.
Generally static methods are nowadays frowned upon since they cannot be dependency-injected.
Your one post was due to Mock testing, where depending on the Mock there may not be a HttpContext, only a controller context. Otherwise, I do use HttpContext.Current, just not in my unit tests.

When was the default AccountController sample changed?

I asked this question over on the asp.net forums, and nobody seems to know what i'm talking about. I'm not sure why that is, but I figured I'll ask here to see if there is anyone with some insight.
Back when MVC2 was released, it included a sample AccountController that wrapped the built-in Membership and FormsAuthentication classes with testable interfaces and services. I read a lot about this, and it was considered a good thing because the Membership and FormsAuthentication classes were not easily testable.
Recently, I generated a new sample project with my up to date (SP1, MVC3, Tools Update, etc..) environment and I find that the AccountController is now much simpler. Gone are the Interfaces and MembershipService and FormsAuthenticationServices. The sample now calls the Membership and FormsAuthentication classes directly.
I'm wondering if anyone knows when this happened and why? Are the testable interfaces no longer considered correct? Was there a technical reason to change this?
The best I can figure is that this happened as a part of the change to remove a possible vulnerability when passing return url's on the open url.
Any insight?
The new model resembles EF's code first approach where the AccountModel is a POCO class. Inside the new API there are no longer abstractions but direct calls to static methods such as FormsAuthentication.SetAuthCookie making this code difficult to unit test. Not something I would recommend basing your real world application code upon.
And, yes, they have fixed a vulnerability inside the LogOn method which was not verifying if the return url is a relative url before redirecting.
Personally I would recommend you using abstractions in order to weaken the coupling between your controller logic and its dependencies. This will make the code easier to unit test.
For me passing all those domain models to views without using view models are total anti-patterns and I have never bothered with them. I simply create an empty project and do the things my way. I mean in the default project they even use ViewBag for Christ sake!
The Account Controller was changed with the MVC3 tools update (When they also included the use of jQuery via Nuget)

Use MVC Custom Model Binder?

I have an MVC app I'm writing. There will be the need for multiple instances of the same page to be open, each accessing different records from a database, these record objects will also need to be passed through a flow of pages, before finally being updated.
What's the best, and most correct, way of acheiving this - should/can I create a custom model binder that links to an object via it's unique ID and then create each record-object in the session, updating them as I go through each one's page flow and then finally calling the update method? Or is there a better way of dealing with this?
Cheers
MH
Technically, that would be possible, but I don't think it is advisable. When you look at the signature of IModelBinder, you will have to jump through some hoops related to the ControllerContext if you want to be able to access the rest of your application's context (such as how to dehydrate objects based on IDs).
It's possible, but so clunky that you should consider whether it's the right approach. In my opinion, a ModelBinder's responsibility is to map HTTP request data to strongly typed objects. Nothing more and nothing less - it is strictly a mapper, and trying to make it do more would be breaking the Single Responsibility Principle.
It sounds to me like you need an Application Controller - basically, a class that orchestrates the Views and the state of the underlying Model. You can read more about the Application Controller design pattern in Patterns of Enterprise Application Architecture.
Since a web application is inherently stateless, you will need a place to store the intermediate state of the application. Whether you use sessions or a custom durable store to do that depends on the application's requirements and the general complexity of the intermediate data.

Should service layer have access to HttpContext?

I'm building an application that roughly follows the repository pattern with a service layer on top, similar to early versions of Conery's MVC Storefront.
I need to implement a page that returns all users except for the current user. I already have GetUsers() methods on the repository and service layers, so the question is where to apply the "except for the current user."
Should the service layer be aware of HttpContext, thus applying this rule? I am tempted to just pass in the current user (id) from the controller to this service method, but it seems cleaner if the service layer was HttpContext-aware and could do this on its own.
One obvious alternative is to apply this rule directly within the Controller, but I'm just not hot on that idea...
Edit - just to comment on the answers: I see the issues with the reverse dependency problem, something I was completely overlooking. I'm marking Mehrdad's as the answer due votes, but everyone has really provided a valuable response worth reading!
Absolutely not. My mindset in designing these kind of things is like this: I assume I need to write a Windows based app along with the Web application and try to minimize dependency on Web specific stuff. Passing HttpContext directly will increase coupling of your service layer to your Web UI layer which is not ideal.
The answer is, no.
Not only should the Service Layer have no dependency on the current Presentation Layer, in my opinion it should have no dependency on the current application. For instance, I would not use a custom AppContext class as JonoW suggested here.
Instead, pass the current user as a parameter to the GetAllUsersExceptForTheCurrentUser method.That way, the service can be used by any application that needs to process users, not only the current application.
You should not create a reverse dependency between your service layer and the web tier. Consider what happens when you want to extend your service layer to work with a forms-based application or windows service. Now you've got to work around the web dependency to get your same methods to work or duplicate some (perhaps, small, but still duplicate) code. You would be better served to extract the user's identifier into something useful in the context of the service layer and use that value with the service layer. Handling the filtering on the web site is also acceptable, though if you do it more than once it would need to be refactored into a common place and the service layer is the natural spot for it.
I find it good practice to build a custom AppContext class which contains my current user object (as well as other contextual data). This class has no references to System.Web. Any service methods that need to be context aware should have an AppContext parameter (e.g. for checking security rights, or getting the current user as in your case). Populate this object in the web-tier and keep it in session if you need to. This way your service layer knows nothing about System.Web.
No. Doing so will make your code harder to test and re-use.
I tend to build an infrastructure interface for this sort of thing (call it IAuthentication or something) and expose a CurrentUser property on it. Then I'd inject this into my service via its a constructor. i.e. public MyService(IAuthentication auth)
Finally you'd can build an HttpContext aware implementation of IAuthentication (say WebAuthentication).
Now when you create your service you create its dependencies as well:
var myService = new MyService(new WebAuthentication());
var otherUsers = myService.GetAllOtherUsers();
If you are using an IoC container the ugly dependency can even go away!

Resources