为什么我的Session [“value”]不会持续存在于各个视图中(asp.net mvc)

时间:2021-11-03 04:02:12

I am electing to do session to store a value that I will need to call and update throughout a handful of controllers and views. I know it is possible to do something like this with a BaseViewModel.cs, or something less session-y, but I am trying to see how Session can possibly solve my needs. That out of the way, here is what I am doing:

我选择进行会话来存储一个值,我需要调用并更新一些控制器和视图。我知道可以使用BaseViewModel.cs做类似的事情,或者更少的会话-y,但我试图看看Session如何能够解决我的需求。这就是我正在做的事情:

Flow

I have a partial view that is rendered on my _layout page like so:

我有一个局部视图,在我的_layout页面上呈现如下:

@Html.Action("OrgSwitch", new { controller = "Common", area = "InkScroll" })

This is a drop down list containing a logged in users organizations. It hits a CommonController that takes care of things like rendering model-bound logic on layout pages. In the CommonController I have this view and a postback, like so:

这是一个包含登录用户组织的下拉列表。它命中了一个CommonController,负责处理在布局页面上渲染模型绑定逻辑的事情。在CommonController中我有这个视图和回发,如下所示:

[ChildActionOnly]
    public ViewResult OrgSwitch()
    {
        var userOrgs = new List<SelectListItem>();
        var user = Ctx.Users.FirstOrDefault(x => x.UserName == User.Identity.Name);
        int key = 0;
        if (user.Organizations.Count > 0)
        {
            TempData["HasOrgs"] = true;
            foreach (var org in user.Organizations)
            {
                if (Session["SelectedOrgKey"] == null)
                {
                    //currently setting selected by primary org id
                    //todo: set selected to tempdata selectedOrgId if there is one.
                    userOrgs.Add(org.OrganizationId.ToString() == user.PrimaryOrgId
                        ? new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = true }
                        : new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = false });
                }
                else
                {
                    key = Convert.ToInt32(Session["SelectedOrgKey"]);
                    userOrgs.Add(org.OrganizationId == key
                        ? new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = true }
                        : new SelectListItem { Text = org.Name, Value = org.OrganizationId.ToString(), Selected = false });
                }
            }

            ViewBag.UserOrgs = userOrgs.OrderBy(x => x.Text);
        }
        else
        {
            ViewBag.UserOrgs = userOrgs;
            TempData["HasOrgs"] = false;
        }
        Session["SelectedOrgKey"] = key;
        return View();
    }

    [HttpPost]
    public RedirectToRouteResult OrgSwitch(string UserOrgs)
    {
        Session["SelectedOrgKey"] = UserOrgs;
        return RedirectToAction("Index", "Recruiter", new { orgId = UserOrgs, area = "InkScroll" });
    }

This more or less on initial load will render the drop down list and default it to the users primary org. If they select something and post back that selection, it will display the selected one by default on subsequent pages.

这或多或少的初始加载将呈现下拉列表并将其默认为用户主要组织。如果他们选择了某些内容并回发了该选项,则默认情况下会在后续页面上显示所选内容。

attempt and failure

I am trying various ways of utilizing the Session value. One area in a viewresult:

我正在尝试各种方式来利用Session值。 viewresult中的一个区域:

 [ChildActionOnly]
    public ViewResult StaffList()
    {
        var user = Ctx.Users.FirstOrDefault(x => x.UserName == User.Identity.Name);

        var model = new List<StaffListViewModel>();
        int key = Convert.ToInt32(Session["SelectedOrgKey"]);
        var org = user.Organizations.FirstOrDefault(x => x.OrganizationId == key);
        if (org.RegisteredMembers != null)
        {
            foreach (var req in org.RegisteredMembers)
            {
                model.Add(new StaffListViewModel
                {
                    UserName = req.UserName,
                    Name = (req.FirstName ?? "") + " " + (req.LastName ?? ""),
                    ImageLocation = req.ImageLocation
                });
            }
        }
        Session["SelectedOrgKey"] = key;
        return View(model);
    }

in here 'key' is coming up empty.

在这里'钥匙'空出来了。

Another try is putting it in the layout cshtml file like so:

另一个尝试是将它放在布局cshtml文件中,如下所示:

<li><a href="@Url.Action("Staff", "Recruiter", new {area="", 
                orgId = Convert.ToInt32(Session["SelectedOrgId"])})">Staff</a></li>

in this one if I hover over the link, the orgId is always equal to 0. Am I messing this up somewhere? Really, I need to have this SelectedOrgId available to any page on the application.

在这一个中,如果我将鼠标悬停在链接上,则orgId总是等于0.我是否在某处弄乱了?真的,我需要将这个SelectedOrgId用于应用程序的任何页面。

1 个解决方案

#1


5  

An answer for posterity sake:

后人的答案:

The code in the question DOES work. The way I am setting and calling session in asp.net mvc works fine. If you have arrived here in a vain search to get session working, then keep looking I guess. The issue I was have related to my control flow and the parameter i was passing in. Once I removed the 'orgId' from the parameters above, I refactored the if/else stuff to just look at session. So the issue was that somewhere in the app I am working on, orgId was not being changed from '0'. Anyway, I am an idiot, but at least I can give you a quick overview of what the hell Session is in asp.net mvc and how easy it is to use:

问题中的代码是否有效。我在asp.net mvc中设置和调用会话的方式很好。如果你来到这里是徒劳的搜索以使会话工作,那么继续看我猜。我遇到的问题与我的控制流和我传入的参数有关。一旦我从上面的参数中删除了'orgId',我重构了if / else的东西,只看会话。所以问题是我正在处理的app中的某个地方,orgId没有从'0'改变。无论如何,我是一个白痴,但至少我可以快速概述一下asp.net mvc中的Session会是什么以及使用起来有多简单:

Setting up app to use session

Session is defaulted to be in process with a timeout of 20 minutes. If you feel like something is overwriting that default you can set it explicitly in your web.config (root web.config on a standard asp.net mvc app):

会话默认为正在进行,超时为20分钟。如果您觉得某些内容覆盖了默认设置,您可以在web.config中明确设置它(标准asp.net mvc应用程序上的root web.config):

 <system.web>
    <sessionState mode="InProc" timeout="60"></sessionState>
    ...other stuff..
</system.web>

I set my timeout above to 60 minutes since I wanted it to stay around a little longer. Standard is 20.

我将超时设置为60分钟以上,因为我希望它能够保持一段时间。标准是20。

Setting a session variable

Pretty damn simple. Do this:

非常简单。做这个:

Session["MyStringVariable"] = "Some value I want to keep around";
Session["MyIntegerVariable"] = 42;

Retrieving the session variable

again, pretty simple, you just need to pay attention to casting/converting the variable to what suits you.

再次,非常简单,你只需要注意将变量转换/转换为适合你的变量。

var localVar = Session["MyStringVariable"].ToString();
var anotherLocalVar = Convert.ToInt32(Session["MyIntegerVariable"] = 42);

So, yeah, I was doing it right, but due to other complexities in my code above, I blamed the big bad Session and not my brain.

所以,是的,我做得对,但是由于我上面的代码中的其他复杂性,我指责了重大的不好的会话而不是我的大脑。

Hope this helps someone! (And if I have the above info wrong, please let me know and I will update!).

希望这有助于某人! (如果我的上述信息有误,请告诉我,我会更新!)。

#1


5  

An answer for posterity sake:

后人的答案:

The code in the question DOES work. The way I am setting and calling session in asp.net mvc works fine. If you have arrived here in a vain search to get session working, then keep looking I guess. The issue I was have related to my control flow and the parameter i was passing in. Once I removed the 'orgId' from the parameters above, I refactored the if/else stuff to just look at session. So the issue was that somewhere in the app I am working on, orgId was not being changed from '0'. Anyway, I am an idiot, but at least I can give you a quick overview of what the hell Session is in asp.net mvc and how easy it is to use:

问题中的代码是否有效。我在asp.net mvc中设置和调用会话的方式很好。如果你来到这里是徒劳的搜索以使会话工作,那么继续看我猜。我遇到的问题与我的控制流和我传入的参数有关。一旦我从上面的参数中删除了'orgId',我重构了if / else的东西,只看会话。所以问题是我正在处理的app中的某个地方,orgId没有从'0'改变。无论如何,我是一个白痴,但至少我可以快速概述一下asp.net mvc中的Session会是什么以及使用起来有多简单:

Setting up app to use session

Session is defaulted to be in process with a timeout of 20 minutes. If you feel like something is overwriting that default you can set it explicitly in your web.config (root web.config on a standard asp.net mvc app):

会话默认为正在进行,超时为20分钟。如果您觉得某些内容覆盖了默认设置,您可以在web.config中明确设置它(标准asp.net mvc应用程序上的root web.config):

 <system.web>
    <sessionState mode="InProc" timeout="60"></sessionState>
    ...other stuff..
</system.web>

I set my timeout above to 60 minutes since I wanted it to stay around a little longer. Standard is 20.

我将超时设置为60分钟以上,因为我希望它能够保持一段时间。标准是20。

Setting a session variable

Pretty damn simple. Do this:

非常简单。做这个:

Session["MyStringVariable"] = "Some value I want to keep around";
Session["MyIntegerVariable"] = 42;

Retrieving the session variable

again, pretty simple, you just need to pay attention to casting/converting the variable to what suits you.

再次,非常简单,你只需要注意将变量转换/转换为适合你的变量。

var localVar = Session["MyStringVariable"].ToString();
var anotherLocalVar = Convert.ToInt32(Session["MyIntegerVariable"] = 42);

So, yeah, I was doing it right, but due to other complexities in my code above, I blamed the big bad Session and not my brain.

所以,是的,我做得对,但是由于我上面的代码中的其他复杂性,我指责了重大的不好的会话而不是我的大脑。

Hope this helps someone! (And if I have the above info wrong, please let me know and I will update!).

希望这有助于某人! (如果我的上述信息有误,请告诉我,我会更新!)。