Nullreferenceexception in User Filter

Asked

Viewed 958 times

0

In my project I made a filter to see if the user is already logged in. To prevent the same Log twice in the system.

According to the answer to my question I make a filter class and search the ID user in session and do all the checking in the database.

What happens is that I’m having a null reference error and I don’t quite know why. I’m passing the ID of the user in the session, but I am not able to capture it at the time of making this check, generating me this error:

Description: An untreated exception occurred during the execution of the current web request. Examine stack tracking for more information about the error and where it originated in the code.

Exception Details: System.Nullreferenceexception: Object reference not defined for an instance of an object.

And the error is being generated on this line:

var idDoUsuario = (long) filterContext.HttpContext.Session["UsuarioID"];  

At the level of more information, I will put the codes of the class I use filter and the action which I use for authentication.

Filter

 void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        var contexto = new EntidadesContexto();
        // Recupero a Id do Usuário logado aqui.
        // Não sei como você está fazendo, então inventei um método
        var idDoUsuario = (long) filterContext.HttpContext.Session["UsuarioID"];           

        var usuario = contexto.Usuarios.FirstOrDefault(u => u.UsuarioID == idDoUsuario && u.Logado && u.SessionID != filterContext.HttpContext.Session.SessionID);

        if (usuario != null)
        {
            // Se o último login foi feito dentro do período de um dia
            if (usuario.UltimoLogin.AddDays(1) > DateTime.Now)
            {
                // Usuário logado em outro lugar.
                usuario.Logado = false;
                contexto.Entry(usuario).State = EntityState.Modified;
                contexto.SaveChanges();
                // Destrua aqui a Session do Usuário se houver uma.                    
            }
            else
            {
                filterContext.HttpContext.Session.Abandon();
                // O login do Usuário expirou.
                var controller = (MeuControllerBase)filterContext.Controller;                    
                filterContext.Result = controller.RedirectToAction("Index", "Autenticacao");                   
            }
        }

Authentication

 [FiltroSessao]
    [HttpPost]       
    public ActionResult Index(String Login, String Senha)
    {
        //verificando login pelo usuario do banco de dados ...
        Usuario login = db.Usuarios.Where(x => x.Login == Login && x.Senha == Senha).FirstOrDefault();
        if (login != null)
        {
            FormsAuthentication.SetAuthCookie(login.Nome.ToString(), false);
            Session.Add(".PermissionCookie", login.Perfil);
            Session.Add("UsuarioID", login.UsuarioID);

            login.Logado = true;
            login.UltimoLogin = DateTime.Now;
            login.SessionID = HttpContext.Session.SessionID;

            db.Entry(login).State = EntityState.Modified;
            db.SaveChanges();

            return RedirectToAction("Index", "Home"); //pagina padrao para todos os usuarios...
        }
        return RedirectToAction("Index");

    }

Just to highlight, I pass the ID user on this line:

Session.Add("UsuarioID", login.UsuarioID);

Any suggestions ?

  • You tried to put a breakpoint on the line that the variable is called to see what is inside the dynamic dictionary Session?

  • Not yet. But I don’t think I’ll get anything back on the intellitrace. (. Because it’s strange he didn’t capture the ID, and he’s already in session. But I’ll see here and tell you.

  • Putting the breakpoint returns it to me: filterContext.HttpContext.Session["User"] = null and idUsuario = 0. Otherwise, it can capture the login and password, minus the ID. :(

  • Well, either there’s a problem with how you’re setting the Session, or it doesn’t work inside the filter for some reason. I’ll have to research it for you.

  • Understood. But just explaining: I play the ID of the user in the session to use in a link that redirects to that specific user’s details page. So I think the problem is because the Session not working inside the filter. =(.

  • Use the Filter [Authorize] wouldn’t solve for you? If the problem is the weather, 1 day for example, this you can set in the web.config

  • @Richarddias not because I need you not to let the user log in twice. That is, as long as the user x is logged in, there is no way to log in. Not in a day, but not while logged in.

Show 2 more comments

2 answers

1

From what I saw in your code, you keep a Ssion with the ID of the User just to recover in filter. It would not be possible to recover the User from the UserName? That way you wouldn’t need to manipulate a Session.

You can get the username of the logged in user by accessing filterContext.HttpContext.User.Identity.Name. If you need to test if the User is logged in, it is possible to check the value of filterContext.HttpContext.User.Identity.IsAuthenticated;

void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        var contexto = new EntidadesContexto();

        var userName = filterContext.HttpContext.User.Identity.Name;           

        // estou assumindo que seu objeto Usuario possui a property UserName
        var usuario = contexto.Usuarios.FirstOrDefault(u => u.UserName == userName && u.Logado && u.SessionID != filterContext.HttpContext.Session.SessionID);

        if (usuario != null)
        {
            // Se o último login foi feito dentro do período de um dia
            if (usuario.UltimoLogin.AddDays(1) > DateTime.Now)
            {
                // Usuário logado em outro lugar.
                usuario.Logado = false;
                contexto.Entry(usuario).State = EntityState.Modified;
                contexto.SaveChanges();
                // Destrua aqui a Session do Usuário se houver uma.                    
            }
            else
            {
                // O login do Usuário expirou.
                var controller = (MeuControllerBase)filterContext.Controller;                    
                filterContext.Result = controller.RedirectToAction("Index", "Autenticacao");                   
            }
        }
  • Good solution. I will test and whether it works or not, I warn here !

0


From what I’ve researched, and from what I’ve seen of your code, [FiltroSessao] is running before you set the value of Session. There are two ways to solve:

  • Change of:

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    

    To:

    void IActionFilter.OnActionExecuted(ActionExecutingContext filterContext)
    
  • Do FiltroSessao receive parameters:

    namespace SeuProjeto.Filters 
    {
        public class UniqueSessionActionFilter : ActionFilterAttribute, IActionFilter
        {
            public long UsuarioId { get; set; }
    
            void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
            {
                var contexto = new EntidadesContexto();
                // Recupero a Id do Usuário logado aqui.
                var idDoUsuario = UsuarioId;     
    
                var usuario = contexto.Usuarios.FirstOrDefault(u => u.UsuarioID == idDoUsuario && u.Logado && u.SessionID != filterContext.HttpContext.Session.SessionID);
    
                if (usuario != null)
                {
                    // Se o último login foi feito dentro do período de um dia
                    if (usuario.UltimoLogin.AddDays(1) > DateTime.Now)
                    {
                        // Usuário logado em outro lugar.
                        usuario.Logado = false;
                        contexto.Entry(usuario).State = EntityState.Modified;
                        contexto.SaveChanges();
                        // Destrua aqui a Session do Usuário se houver uma.                    
                    }
                    else
                    {
                        filterContext.HttpContext.Session.Abandon();
                        // O login do Usuário expirou.
                        var controller = (MeuControllerBase)filterContext.Controller;                    
                        filterContext.Result = controller.RedirectToAction("Index", "Autenticacao");                   
                    }
                }
            }
        }
    }
    

    Use:

    public class ControllerExemplo 
    {
    
        public long ExemploUsuarioId { get; set; }
    
        public ControllerExemplo() {
            ExemploUsuarioId = HttpContext.Current.Session["UsuarioID"]);
        }
    
        [FiltroSessao(UsuarioId = ExemploUsuarioId)]
        public ActionResult Index() { ... }
    }
    
  • That line: var idDoUsuario = User;, would be the one I have right ? So: var idDoUsuario = (long) filterContext.HttpContext.Session["User"]; ?

  • Note that I changed to Filter accept an external parameter, so you do not use Session inside Filter.

  • Passeporaquioiddousuario would then be: Httpcontext.Session["User"]; ?

  • @Érikthiago Isso.

  • Ué, the Httpcontext ta giving error: 'An Object Reference is required for the non-static field, method, or Property "System.Web.Mvc.Controller.Httpcontext.get"'. Overload error ? Ta thus: [Filter(User = Httpcontext.Session["User"])].

  • Define a variable in the construction of Controller who receives the UsuarioId. Better than using the HttpContext directly in the attribute.

  • Could you put an example in the question ?

  • @Érikthiago Feito.

  • Good. But just one thing: this Current not caught at all, then I’m taking it. It works also right ?

  • @Érikthiago It’s supposed to work yes.

  • Dude, something’s wrong. It doesn’t work. From the same bug as before: 'An Object Reference is required for the non-static field, method, or Property'...

  • That mistake only comes out when I declare Static: public Static long User { get; set; }. This is wrong right ?

  • No, it can stay that way.

  • With the Static ? But still the error. = (. This one: An attribute argument must be a Constant Expression, typeof Expression or array Creation Expression of an attribute Parameter type

  • And if I make the first choice of that: 'Iactionfilter.Onactionexecuted' in Explicit interface declaration is not a Member of interface

Show 10 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.