0

I am creating a .Net Core web API V3 project and in that project, I have a requirement:

On every request check the SESSION, if it is ACTIVE then proceed else STOP the request and throw BAD REQUEST error.

Now In my application, I have a SESSION table in my database and in that table I have a few columns among which I have

Active (bit),

Last Activity (Datetime(2)),

Ended (Datetime(2)) column

What I need:

1- I need to update LastActivity column on every REQUEST on API.

2- And in that context, we should validate that we have already set the session timeout value to 2 minutes in appSettings.json so then on every request we should first validate that if the time from LastActivity and current DateTime minutes is not greater then 2 minutes, if it is, then throws BadRequest error and stop the execution, else let it go and update the LastActivity column to current DateTime.

What I Have Already Done (And is not working)

using System;
using System.Linq;
using DataAccess.Dtos;
using DataAccess.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Service.Contracts;

namespace Motorlogs.API.Shared
{
    public class SessionActionFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            ISessionService _ISessionService = null;
            IConfiguration _IConfiguration = null;

            if (LoggedInUser.SessionId != null)
            {
                Session session = _ISessionService.GetSessions(x => x.SID == LoggedInUser.SessionId).FirstOrDefault();

                if (session != null)
                {
                    if (session.Active == false)
                    {
                        context.Result = new BadRequestObjectResult("Session Expired! Please login again.");
                        return;
                    }

                    if (!session.LastActivity.HasValue)
                    {
                        session.LastActivity = DateTime.Now;
                        _ISessionService.UpdateSession(session);
                    }
                    else
                    {
                        var lastActivityTime = session.LastActivity;
                        var currentTime = DateTime.Now;
                        var requestDuration = currentTime.Subtract((DateTime)lastActivityTime);
                        var sessionTimeOutMinutes = TimeSpan.FromMinutes(int.Parse(_IConfiguration.GetSection("AppSettings:SessionExpiryTime").Value)).Minutes;

                        if (requestDuration.Minutes >= sessionTimeOutMinutes)
                        {
                            session.Ended = DateTime.Now;
                            session.Active = false;
                            _ISessionService.UpdateSession(session);
                            context.Result = new BadRequestObjectResult("Session Expired! Please login again.");
                            return;
                        }
                        else
                        {
                            session.LastActivity = DateTime.Now;
                            _ISessionService.UpdateSession(session);
                        }
                    }
                }
            }
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            // our code after action executes
        }
    }
}

And in Startup.cs

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {

            services.AddDbContext<MotorlogsContext>(x =>
                x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddMvc(option => option.EnableEndpointRouting = false)
                //.AddNewtonsoftJson(options =>
                //    options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects)
                .AddNewtonsoftJson(options =>
                    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

            services.AddCors(c =>
            {
                c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
            });

            services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(
                            Encoding.ASCII.GetBytes(
                                Configuration.GetSection("AppSettings:Token").Value)),
                        ValidateIssuer = false,
                        ValidateAudience = false
                    };
                });

            services.AddDistributedMemoryCache();

            services.AddSession(options =>
            {
                options.IdleTimeout =
                    TimeSpan.FromMinutes(int.Parse(Configuration.GetSection("AppSettings:SessionExpiryTime")
                        .Value));
            });

            var identitySettingsSection = Configuration.GetSection("EmailConfiguration");
            services.Configure<EmailConfiguration>(identitySettingsSection);
            services.AddAutoMapper(typeof(Startup));

            services.AddSignalR(hubOptions =>
            {
                hubOptions.EnableDetailedErrors = true;
                hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(1);
            });

            services.AddHttpContextAccessor();

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddSignalR();
            services.AddHostedService<NotificationsHostedService>();

            // This is the line I added for my SessionActionFilter
            services.AddScoped<SessionActionFilter>();

            return ConfigureIoC(services);
        }

Article I referred:

https://code-maze.com/action-filters-aspnetcore/

Thanks.

2
  • What's the problem now? Commented Jul 22, 2020 at 8:34
  • My created Action Filter is not hitting. Commented Jul 22, 2020 at 10:08

1 Answer 1

1

If you want to add a filter globally for all controllers, actions, you should configure it like below:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(SessionActionFilter));
    });
}

For more details, refer to the document of filters.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.