How to use session Data in a different Controller View?

2.1k Views Asked by At

ApplicationDBContext.cs

public DbSet<Register> RegisterAccount { get; set; }

Register Model

public class Register
{
    [Key]
    public int RegisterId { get; set; }
    [Required]
    [DataType(DataType.EmailAddress, ErrorMessage = "Please enter a valid e-mail address")]
    public string Email { get; set; }
    [Required]
    [Display(Name = "Full Name")]
    public string Name { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [MinLength(5, ErrorMessage = "Password length cannot be less than 5")]
    public string Password { get; set; }

    [NotMapped] // Does not effect the database
    [Compare("Password")]
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Confirm Password")]
    public string ConfirmPassword { get; set; }

}

I want to use session data in various controllers, how do I manage that?

LoginController.cs

public IActionResult Login(Login user)
{
        if (ModelState.IsValid)
        {
            var obj = _db.RegisterAccount.Where(u => u.Email.Equals(user.Email) && u.Password.Equals(user.Password)).FirstOrDefault();

            if (obj != null)
            {
                user.RegisterId = obj.RegisterId;
                _db.LoginAccount.Add(user);
                _db.SaveChanges();
                HttpContext.Session.SetObjectAsJson("Register", obj);
                return RedirectToAction("LoggedIn");
            }
        }

        ModelState.AddModelError("", "Some Error Occured");

        return RedirectToAction("Login");
}

public IActionResult LoggedIn()
{
        var userDetails = HttpContext.Session.GetObjectFromJson<Register>("Register");
        int? thisUserID = Convert.ToInt32(userDetails.RegisterId);

        if (thisUserID != null)
        {
            TempData["Users"] = userDetails;
            return View(); 
        }
        else
        {
            return RedirectToAction("Login");
        }
}

SessionExtension.cs

public static class SessionExtension
{
    public static void SetObjectAsJson(this ISession session, string key, object value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T GetObjectFromJson<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
    }
}

LoggedIn.cshtml View

@using Microsoft.AspNetCore.Http

@inject IHttpContextAccessor HttpContextAccessor


@{
    var userdetails = HttpContextAccessor.HttpContext.Session.GetObjectFromJson<Register>("Register"); // userdetails is available
}

<h1>Hi @userdetails.Name</h1>

Here, the username is displayed.

Say I have another controller Home and in the Index View I want to access the details of logged in user, how do I do it? I have tried

HomeController/Index.cshtml view

@using Microsoft.AspNetCore.Http

@inject IHttpContextAccessor HttpContextAccessor


@{
    var userdetails = HttpContextAccessor.HttpContext.Session.GetObjectFromJson<Register>("Register"); // userdetails remains null
}

<h1>Hi @userdetails.Name</h1>

Home Controller Index

 public IActionResult Index()
        {
           
            return View();
        }

What I want to do is to display the user name in my home controller index view as well as my login controller index view whenever the user has logged in.

1

There are 1 best solutions below

7
Rahul Sharma On BEST ANSWER

In order to show your Session on your View, you can inject IHttpContextAccessor implementation to your view and use it to get the Session object as required:

@using Microsoft.AspNetCore.Http
@inject IHttpContextAccessor HttpContextAccessor
@{
    //Get object from session
    var mySessionObject = HttpContextAccessor.HttpContext.Session.GetObjectFromJson<Register>("Register");
 }

<h1>@mySessionObject.Name</h1>
//So on

You do not need TempData for your case since you are already setting up your Session. TempData is used when you want to persist your variables from one Controller action to another to use them in the action method itself.

Now regarding your problem that the Session is not accessible in other Controller, you need to add services.AddDistributedMemoryCache() in order to have some place to store your Session data. You can read more on MSDN

In your Startup.cs, add the following:

public void ConfigureServices(IServiceCollection services)
{
  //Added for session state
  services.AddDistributedMemoryCache();

  services.AddSession(options =>
  {
     options.IdleTimeout = TimeSpan.FromMinutes(10);               
  });
}