简体   繁体   中英

Call a controller method in a view

I've got an asp.net core application in Visual studio. In a auto-created view (Events/index.cshtml) I want to call this method from the EventsController.cs

public Boolean IsInRole(string Role)
{
    Boolean roleMembership = false;

    if (HttpContext.Session.GetInt32("ID") != null)
    {
        if (HttpContext.Session.GetString("Role") == Role)
        {
            roleMembership = true;
        }
    }

    return roleMembership;
}

My idea was to call this method at the top of the view with

@if(IsInRole("Admin")) {
    show some content
}

How can I achieve this task?

You may move that logic to a separate class. Since this code is using HttpContext.Session , it is a good idea to create an interface for your class and let this class be your concrete implementation using HttpContext.Session . You can inject the needed implementation in your controller or view using the Dependency Injection framework.

public interface IUserAccessHelper
{
    bool IsInRole(string role);
}
public class UserAccessHelper : IUserAccessHelper
{
    private readonly IHttpContextAccessor httpContextAccessor;

    public UserAccessHelper(IHttpContextAccessor httpContextAccessor)
    {
        this.httpContextAccessor = httpContextAccessor;
    }
    public Boolean IsInRole(string role)
    {
        Boolean roleMembership = false;

        if (httpContextAccessor.HttpContext.Session.GetInt32("ID") != null)
        {
            if (httpContextAccessor.HttpContext.Session.GetString("Role") == role)
            {
                roleMembership = true;
            }
        }
        return roleMembership;
    }
}

Now make sure to to register this in the ConfigureServices method in Startup.cs

services.AddTransient<IUserAccessHelper, UserAccessHelper>();

Now in the razor view, you can inject this dependency. Yes, DI is possible in views now :)

@inject IUserAccessHelper UserAccessHelper
@if (UserAccessHelper.IsInRole("SomeRole"))
{
    <h2>In Role</h2>
}
else
{
    <h2>Not in Role</h2>
 }

You can inject the same IUserAccessHelper inside your controller via constructor injection.

public class HomeController : Controller
{
    private readonly IUserAccessHelper userAccessHelper;
    public HomeController(IUserAccessHelper userAccessHelper) 
    {
        this.userAccessHelper = userAccessHelper;
    }
    public ActionResult Create()
    {
       // you can use this.userAccessHelper.IsInRole("abc")
       // to do  :return something
    }
}

Since you are injecting the needed implementation via dependency injection, now you can unit test your controller method. Your controller code does not have any tight coupling to HttpContext now . You can create a MockUserAccessHelper (which does not use HttpContext) for your unit tests and use that as needed.

Since this is a generic method not specific to any controller, move it into a separate class.

Then you can reference that class's namespace in your view with a @using directive (almost exactly like you would in a .cs file), and then call the method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM