MVC3 - Access User context in Controller base class - asp.net-mvc-3

I have the following code in a view
#User.Identity.Name
Works fine.
The same code in a custom controller base class doesn't work. The User object is null
public class AdminBaseController : Controller
{
public AdminBaseController()
{
string userId = User.Identity.Name;
//if(!AnAdmin)
//redirect to UnauthorizedPage
I want to use this base class in place of System.Web.MVC.Controller as the base for all my Administration screens. This way I can redirect anybody that is not an admin (NTLM authentication).
Why the nulls? How do I get to my context? (HttpContext and something called ControllerContext are null too)
After some tinkering, things are null in the Controller constructors. The Action Methods work fine. Question still stands, but it appears I need help choosing an alternative implementation.

You should use Authorization filter, ASP.NET MVC Authorization. Also check Understanding Action Filters.
Or you can override Initialize method on Controller, User object will be initialized.

I just tried to access the 'Name'-property in a function within a controller class. That wasn't an issue and it wasn't null.
My best guess is that you can't access this object in the constructor of a controller.

Related

how to share the token between classes

I have having a design issue with asp.net web-api and would like to know how to solve this problem
public abstract class BaseApiController<TEntity> : ApiController where TEntity : Entity
{
protected string GetUsername()
{
return Utilities.GetUsername(Request.Headers.Authorization);
}
//some other code
}
public class StakeholderApiController : BaseApiController<Stakeholders>
{
ILogger _logger = new CustomApiLogger("StkhManager", GetUsername())
//some other code
}
now the problem I have is:
I have the BaseApiController which I am using the share certain functionality between all ApiControllers.
And then I have some specified ApiController for certain not shared functionality.
Now while doing logging, I do want to log the logged in user's name, the problem is I have to pass it everytime I create a new instance, is there a way I can make the logged in user's name global for the current api request so that it can be accessed everywhere.
I cannot make it static, otherwise for others request it will give wrong username.
is there a way I can avoid passing it everytime. Given that webapi is stateless, so session cant be used, is there anyother way??
I am using angularjs front end, hence I am NOT using any authorization technique provided by MVC/.net
Note:
I cannot move creation of Logger to base class for certain reasons
This is just one example, I want to use the logged in user's name in many other place. Hence dont want to pass it around.
There is a standard pattern in setting and accessing principal with ASP.NET Web API. From an ApiController such as your BaseApiController, you can just use the User property to retrieve the same. To set it, typically, the HttpRequestContext is obtained from the request object and the principal is set like so.
Request.GetRequestContext().Principal = new ClaimsPrincipal(...);
BTW, you can access the current request object in the Web API pipeline pretty much from anywhere.

Umbraco ApiController actions wont map to http-verb

I have been working some with the Web API before.. and as far as I can remember..
The actions in (at least the new version) is called Get,Post,Delete,Put etc...
and these actions are triggered depending of the http-verb in the request..
So for instance you might have an ApiController called UserApiController..
and if you do a request to /api/user with the POST http-verb.. then the Post-action in that controller will be triggered/executed..
However....
it seems like Im having some trouble with this using the UmbracoApiController... for some reason it wont execute post or get or any other action mapped to the http-verb..
Any ideas?.. is there any other way to sort of force a method to be executed depending on the http-verb?
My current code is:
public class MyController : UmbracoApiController
{
[HttpPost]
public bool Post()
{
return true;
}
}
I have placed a breakpoint with in the action..
The reason they won't be accepted is you're using the wrong attribute - HttpPost is part of the System.Web.Mvc namespace, whereas Web API is part of the System.Web.Http namespace.
You have to use AcceptVerbs("POST") instead.

MVC Autofac ExtensibleActionInvoker stops me using interface parameters

I have a problem with the Autofac ExtensibleActionInvoker interacting with the MVC ModelBinder when using interfaces for parameters. The background is as follows:
I am building a MVC application and I am using Autofac MVC3's ExtensibleActionInvoker to inject my services as parameters to my actions, e.g.
public ActionResult Test( IMyService service)
{
//A new instance of service is created by Autofac ExtensibleActionInvoker
return View();
}
This works really well and makes for a really clean design (see Alex Meyer-Gleaves post for more information on this approach). I want to use this method as I am producing a code generator to create actions, views, services and DTOs and a per-action service approach makes this easier.
However I also want to use interfaces for the parameters in action classed which receive input from an HttpPost action. This is because I use DI to create classes outside each layer. If I change the DefaultModelBinder to use DI to create the class (see page 595 of Steve Sanderson's book on MVC3 on how to do this) this this works fine, e.g.
[HttpPost]
public ActionResult Test(ITestClass dataComingFromView)
{
//model binder creates the class via DI and then binds it to the data from the post
return View();
}
However in the above simple example above I get a conflict with the ExtensibleActionInvoker enabled, i.e.
Without ExtensibleActionInvoker enabled the method above works fine, i.e. the extended
DefaultModelBinder uses DI to create the TestClass class and modelbinder binds
input from the view to the fields in the class.
With ExtensibleActionInvoker enabled it does not work, i.e. I get an empty TestClass class with no binding. I assume the ExtensibleActionInvoker takes precedence over the model binder and just creates an empty TestClass class.
(Just for completeness I should say that if I just use MVC "out of the box", i.e. no new DefaultModelBinder and no ExtensibleActionInvoker enabled, then it says you cannot use an interface as an Action method parameter.)
My question for anyone with better Autofac knowledge than me is: can I change the Autofac ExtensibleActionInvoker to select what it binds to? All my injected service classed start with IService so I could filter on that. I know you can do that in Autofac elsewhere but couldn't see anything to do that with ExtensibleActionInvoker, but maybe I missed it.
Any help would be appreciated.
Jon Smith - Selective Analytics
You are correct that the problem is caused by the ExtensibleActionInvoker class. If you look at the source for it, there is a method called GetParameterValue(). See below:
protected override object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
if (_injectActionMethodParameters)
return _context.ResolveOptional(parameterDescriptor.ParameterType) ?? base.GetParameterValue(controllerContext, parameterDescriptor);
return base.GetParameterValue(controllerContext, parameterDescriptor);
}
This method overrides the method that eventually uses the MVC framework's model binder infrastructure. What this means, is that the ActionInvoker tries to resolve the parameter using AutoFac first, and if it fails, falls back to the default functionality. Based on the results you are getting, it seems that your AutoFac configuration must be setup to provide a default resolution of ITestClass.
In order to register a custom ModelBinder with AutoFac you have a couple options. You can decorate the view model with a ModelBinderTypeAttribute or you can do it in your configuration with the custom extension methods found in RegistrationExtensions.
One article I found looks like it provides an easy solution to a similar issue (see the end), but I have not tested this personally.
Having now worked on this problem I found a simple answer. My problem was due to me not really understanding how the MVC Model Binding worked.
If you look at my orginal problem I had created a DefaultModelBinder to allow me to use interfaces as my model parameters (see original question at the top). This was added after me including the Autofac's ExtensibleActionInvoker to bind my IService types. The problem was that the two DI approaches clashed.
The answer was that the DefaultModelBinder was sufficient to bind both my data classes and the Service definitions, so I do not need Autofac's ExtensibleActionInvoker. For completeness I have included the DefaultModelBinder code in case it is useful to anyone else.
public class DiModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
return modelType.IsInterface
? DependencyResolver.Current.GetService(modelType)
: base.CreateModel(controllerContext, bindingContext, modelType);
}
}
Note that I only call the DependencyResolver if the modeltype is an interface as I don't pass abstract classes between layers. Any alternative is to always call the DependencyResolver and then call the base.CreateModel if the DI does not resolve the type. I didn't do this because calling the DependencyResolver is slightly expensive so I only call it when I know I need it.

Where to place the login/authentication related actions in MVC

I've searched around and found that when implementing an authentication module in MVC architecture some people opt to place the login related actions in the User controller while others place it in a controller dedicated to authentication only.
In pseudo-java-like code:
class UserController extends Controller {
public login() {
//...
}
}
Accessed with http://mydomain.com/user/login.
vs.
class AuthController extends Controller {
public login() {
//...
}
}
Accessed with http://mydomain.com/auth/login.
I would like to know which approach is better, and why. That is, if there's really any difference at all.
Thanks in advance.
IMO:
The stuff handling the actual login should be in a controller, like the UserController you suggested.
Persistent authentication (e.g. checking whether a user is logged in) could just be some functions in the UserModel, which you call from any controller.
Depending on the situation, you may want some kind of global function that redirects to the login page if the user is not logged in.
I prefer the first approach, with the simple reasoning that the authentication is an action pertaining to the user. And in general, I prefer my controllers to reflect the real-life entities my logic deals.

Spring: controller inheritance using #Controller annotation

I'd like to be able to create a base controller in my Spring app that, among other things, determines if a user is a registered user or not. This base controller, following the template design pattern, would contain an abstract protected method that controller subclasses would implement.
The abstract method would have passed to it an instance of User, registered or otherwise. However, I have no idea how I would do this since it seems that by using controllers purely using the #Controller annotation each controller is free to define their request handling method however they like.
Would creating some sort of user service class that is injected into each controller and used to validate a user be one way to get around this? This begs the question (at least for me) how does such a controller get a hold of a HttpServletRequest or the Session object?
Thanks.
Define an abstract BaseController, with no annotations
Define concrete and abstract methods
Call these methods from subclasses (which are annotated with #Controller) whenever needed.
I think the Base Controller is not a good idea if the only code it is to have is for UserAuthentication...instead use Spring security. This is the best option.
Alternatively, you can have methods like this...take a look at the Spring reference..
#Controller("loginController")
public class LoginController {
#RequestMapping(value="/login.do", method=RequestMethod.POST)
public String login(Model model, HttpServletRequest request) {
String userIdFromRequest = (String)request.getParameter("userId");
String password = (String)request.getParameter("password");
boolean verified = ...send userIdFromRequest and password to the user service for
verification...
if (verified){
request.getSession().setAttribute("userId", userIdFromRequest);
}
}
//More Methods
}
Did it help?
-SB
The basic problem is that annotational bootstrapping is not polymorphic. I found this paper useful: http://sanguinecomputing.com/design-pattern-for-hierarchical-controller-organization-with-annotational-configuration-spring-mvc-3/

Resources