0

Im trying to pass a users name in ASP.NET MVC 4 after they have logged in but I cant figure out a way to get the data to transfer.

Here is the Login Action named "Auth" that gets the users info after its set.

public string name;
account userInfo;

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Auth(account user)
{
    if (ModelState.IsValid)
    {
        userInfo = GetUser(user);
        if (userInfo.rank == "a")
        {
            Session["IsAdmin"] = true;
            Session["IsMember"] = true;
            name = userInfo.username;
            return RedirectToAction("Index", "Mod");
        }
        if (userInfo.rank == "member")
        {
            Session["IsMember"] = true;
            name = userInfo.username;
            return RedirectToAction("Index", "Post");
        }
    }

    name = userInfo.username;
    return View("Login");
}

After the name variable is set, i try to get the value from my PostController's Index View which is the index of my site using inheritance to display but the variable resets to null.. Heres the Index action used to call the name variable from my AccountController where the Auth Action resides.

    public class PostController : AccountController
    {
        public ActionResult Index(int? id)
        {

          /*EncryptConString();*/
            int pageNum = id ?? 0;
            IEnumerable<Post> posts = 
                (from post in db.Posts
                where post.time < DateTime.Now && post.category == "Blog Post"
                orderby post.time descending
                select post).Skip(pageNum * postCount).Take(postCount +1);

            ViewBag.IsPreviousLinkVisible = pageNum > 0;
            ViewBag.IsNextLinkVisible = posts.Count() > postCount;
            ViewBag.PageNumber = pageNum;
            Session["ShowSide"] = true;
            ViewBag.showSidebar = showSidePanel;
            ViewBag.SecAbvPosts = secAbvPosts;
            ViewBag.IsAdmin = IsAdmin;
            ViewBag.IsMember = IsMember;
            ViewBag.Name = name;
            return View(posts.Take(postCount));
        }
    }

Is there another way I can do this? Im trying to achieve getting the users info after they login to display it on the index page along with their profile pic.. Please help!!

tereško
  • 58,060
  • 25
  • 98
  • 150
Dezmen Ceo Sykes
  • 179
  • 1
  • 4
  • 16
  • Each request handles by a new instance of the controller. Think about how you can make it stateless. Caching and the session can be used where needed. Keep in mind that using the session forces requests to be processed serially rather than asynchronously. – Daniel Little Jul 25 '13 at 02:43

4 Answers4

1

The value is not available after the redirect because you will have a brand new instance of the controller class as a result of the redirect. No data will be persisted between redirects.

One option you have is to use TempData as a temporary storage - just long enough to pass it from one request to the next. It's backed by session, but it has a much more limited lifespan. Read more here:Using Tempdata in ASP.NET MVC - Best practice

One thing to keep in mind though is that anything session based will not always work well in load balanced systems since you depend on hitting the same server with every request. I usually recommend using session sparingly. In many cases it may actually be easier to just reload the user record from the DB on the second action method.

Community
  • 1
  • 1
TGH
  • 38,769
  • 12
  • 102
  • 135
  • Would this work between 2 differnt classes? unlike Viewbag and ViewData? – Dezmen Ceo Sykes Jul 25 '13 at 02:41
  • It will work between two different requests, so yes. It is basically just session state, but it's removed from memory once it's read by the second controller action. – TGH Jul 25 '13 at 02:43
  • How about this TempData["Name"] = user.Name; name = TempData["Name"]; This in my post controller set the ViewBag.Name = name; That should do it then erase the data after that request? – Dezmen Ceo Sykes Jul 25 '13 at 02:51
  • Yes, it will automatically be cleared out when it's retrieved by the second action – TGH Jul 25 '13 at 02:53
  • Thanks bro it worked! Now i can transfer it, grad the info, and assign it for a new instance in the Post Controller and shoot from there! Thanks bro! And everyone who helped! – Dezmen Ceo Sykes Jul 25 '13 at 03:00
  • @DezmenCeoSykes One thing I'd add to help with understanding. Viewbag and ViewData is for sharing data between a Controller and a View whereas TempData is for sharing data between controllers. Purists don't use Tempdata at all and tend to rely on a RESTful approach. I like TempData and absolutely believe it has a place in MVC programming. – onefootswill Jul 26 '13 at 04:40
1

A Controller only lasts for the duration of the web request. Once they login.. that controller is done. The next controller will fire up with a brand new instance.. and when it does, name will be null (as you've seen).

Your entire setup is very very strange and really against best practices. What I would say is that you should just get the user info again in your new request. How you go about identifying the user given your current setup is another issue though. You could store their username in Session too.. but really, you should be using the Membership classes provided by .NET OR you should at least be signing them in with a cookie that you can retrieve via the HttpContext.Current.Identity property. That way you can identify them by name and retrieve their details again.

Also of note: You're mixing dynamic typing (ViewBag) with strongly typed models. Pick one (strongly typed is preferred/best practice).

Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
  • I see what you mean, TGH pointed out the use for TempData first, but I appreciate your help man! I'll look into the Current.Identity too – Dezmen Ceo Sykes Jul 25 '13 at 03:01
0

I don't think you can achieve this using inheritance. Even though the AccountController is a parent type, the actual objects which are instantiated will be different as the http request travels its route. When you redirect to the PostController, the PostController will be an entirely different object to the AccountController, not the same object with 2 different static types.

You could chuck the name in TempData and grab it back from there in the redirected target action.

onefootswill
  • 3,707
  • 6
  • 47
  • 101
0

This is the wrong way to be doing authentication in MVC. You should be using either Windows Authentication, or FormsAuthentication, or some other mechanism that implements IIdentity and IPrincipal.

You can see an example of how this works by generating a default internet template application and looking into the AccountController code, and look for FormsAuthentication. You would then use the [Authorize] attribute to control access.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291