Monolithcode
Monolithcode

Reputation: 618

MVC ActionFilterAttribute - Get a value from the action

In MVC I have a service registered in Startup I use to validate actions like so:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    //services.AddCaching();
    services.AddSession();
    services.AddMvc();
    services.AddScoped<SessionDetails>();
    //services.AddTransient<IAppSettings, AppSettings>();
    services.AddSingleton(Configuration);

    services.AddSingleton(MobileUnitOfWork);
    //services.AddTransient<IMobileUnitOfWork, MobileUnitOfWork>();
    services.AddScoped<RoleItemKey>();

    //Custom Attributes
    services.AddScoped<SiteSetting>();
    services.AddScoped<ValidationService>();
    //services.AddScoped<RequestHelper>();

    //services.AddEntityFramework()
    //    .AddSqlServer()
    //    .AddDbContext<QuotesAppContext>(options => options.UseSqlServer(Configuration["Data:ConnectionString"]));
}

It is then plopped on whatever requires a check on access.

Controller:

[ServiceFilter(typeof(ValidationService))]
public IActionResult MyDetails()
{
    ControllerContext.RouteData.Values.Add("RoleItemKey", "MOBILE_MYHOLIDAYS_PAGE");
    ControllerContext.RouteData.DataTokens.Add("RoleItemKey", "MOBILE_MYHOLIDAYS_PAGE");
    HttpContext.Session.SetString("RoleItemKey", "MOBILE_MYHOLIDAYS_PAGE");
    ViewBag.RoleItemKey = RoleItemKey.MOBILE_MYHOLIDAYS_PAGE;
    return View("~/Views/User/MyDetails.cshtml", GetDetailsModel());
}

All I need to do is pass a value from the executing action to be read by the ActionFilterAttribute. Now because I need and want the service initialising in the Startup.cs I cannot find a way to pass a value - please tell me what I'm overlooking.

As you can see I have tried routedata, session info... but whatever is set in the actual action I cannot read in the ActionFilterAttribute, it just returns null for all of it.

Can anyone tell me with this setup, how I can read a value from the action that is being executed?

Service:

public class ValidationService : ActionFilterAttribute
{    
    private IConfiguration _config;
    private IMobileUnitOfWork _services;
    private Controller _controller;
    private ActionExecutingContext _context;
    private readonly IHttpContextAccessor _contextAccessor;
    private ISession _session => _context.HttpContext.Session;
    public string Moons;

    public ValidationService(IConfiguration config, IMobileUnitOfWork unitOfWork)
    {
        _config = config;
        _services = unitOfWork;
    }

    /// <summary>
    /// Ensures the page is validated before being directed
    /// </summary>
    /// <param name="context"></param>
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var controller = context.Controller as Controller;
        var moo = controller.HttpContext.Session.GetString("CascadeSessionToken");
        var mos = controller.HttpContext.Session.GetString("RoleItemKey");
        _context = context;
        _controller = controller;
        _controller.ViewBag.LoggedIn = true;

        base.OnActionExecuting(context);
        Validate("");
   }

Upvotes: 0

Views: 2912

Answers (2)

Monolithcode
Monolithcode

Reputation: 618

Resolved it. Decided to take out the two services from the initialiser and get them from the controller instead - now I can just pass in my required key.

Upvotes: 0

Set
Set

Reputation: 49789

You need to use HttpContext.Items for this. To store value:

context.Items["key"] = value;

and to get value back

var value = context.Items["key"];

Upvotes: 0

Related Questions