1

I am trying to set role to the logged user but I can't get the logged user name in my non-action method called from another controller. I am missing something, because I get the error: "Object reference not set to an instance of an object", which I understand because the logged user name comes null in my RegisterAsUser() method. Do I call the non-action method ok? Tell me what I am doing wrong. Thank you in advance!

My code:

The non-action method:

    [NonAction]
    [Authorize]
    public void RegisterAsUser()
    {
        //Add User role
        var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
        string role = "User";
        //Create Role User if it does not exist
        if (!roleManager.RoleExists(role))
        {
            var roleResult = roleManager.Create(new IdentityRole(role));
        }

        var store = new UserStore<ApplicationUser>(new ApplicationDbContext());
        var userManager = new UserManager<ApplicationUser>(store);
        string userId = User.Identity.GetUserId();

        if (!Roles.IsUserInRole("Admin"))
        {
            var result = userManager.AddToRole(userId, role);
        }
    }

Where I call the RegisterAsUser() method in other controller:

public ActionResult Create()
    {
        //set the logged user role to "User"
        IdentityRoleController roleController = new IdentityRoleController();
        roleController.RegisterAsUser();

       ... some other code here...
        return View();
    }

enter image description here

Update: I noticed that If I change the non-action method with an ActionResult one and call it from the url it assigns the role to the logged user. So I assume that instantiating a controller with it's non-action method in another controller it's wrong but I will like to know why.

Dan Romulus
  • 95
  • 2
  • 13
  • Instantiating a controller in another controller is evil. Don't so it. Create a service method in your web project that both controllers can use. – Gert Arnold Feb 10 '17 at 19:02
  • ok, thank you I will do it – Dan Romulus Feb 10 '17 at 19:06
  • @Gert Arnold It is possible to explain more, what you mean about the service method please? I googled it and it returns something about a web service method. It is what you mean? – Dan Romulus Feb 10 '17 at 19:30
  • 1
    @DanRomulus He means to use the service-interface design methodology. https://blogs.msdn.microsoft.com/simonince/2008/08/25/the-service-interface-pattern/ – nurdyguy Feb 10 '17 at 21:15
  • I think it is too much for a school project like mine... – Dan Romulus Feb 10 '17 at 21:35

2 Answers2

1

there are other ways for this problem ex:

  1. pass userId from Create (Parent action) to RegisterAsUser (Child action) and child action as a AllowAnonymos (filter).

  2. use service layer instead of child action (and this is important in OOP).

hamid_reza hobab
  • 925
  • 9
  • 21
0

The problem I was facing, instantiating a controller A in other controller B, was that I was not getting the controllerContext from controller A to it's instance in controller B and other functionalities. To overcome this i used this:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);

...from this post: How to call another controller Action From a controller in Mvc [the second solution]

Update: I found a better solution:

  • Created another folder to store my RegisterAsUser() public method as a service
  • using this in the RegisterAsUser() public method:

HttpContext.Current.User.Identity.Name to get the current user along with

using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework;

  • instantiate in the Create controller with :

var roleService = new IdentityRoleService(); roleService.RegisterAsUser();

to assign "User" role to logged user

Thank you all!

Community
  • 1
  • 1
Dan Romulus
  • 95
  • 2
  • 13