Как использовать сеансы в приложении ASP.NET MVC 4?

113

Я новичок в ASP.NET MVC. Раньше я использовал PHP, и было легко создать сеанс и выбрать пользовательские записи на основе переменных текущего сеанса.

Я повсюду искал в Интернете простое пошаговое руководство, которое может показать мне, как создавать и использовать сеансы в моем приложении C # ASP.NET MVC 4. Я хочу создать сеанс с пользовательскими переменными, к которым я могу получить доступ из любого места в моих контроллерах и иметь возможность использовать переменные в моих запросах LINQ.

Туто Поль Гаотингве
источник
2
Эта статья может быть интересна: brockallen.com/2012/04/07/think-twice-about-using-session-state
Daniel Hollinrake

Ответы:

160

Пытаться

//adding data to session
//assuming the method below will return list of Products

var products=Db.GetProducts();

//Store the products to a session

Session["products"]=products;

//To get what you have stored to a session

var products=Session["products"] as List<Product>;

//to clear the session value

Session["products"]=null;
Жобер Энамно
источник
3
Спасибо, Джоберт! ты дал мне идею! просто интересно .., можно ли добавлять пользовательские переменные в сессию во время входа в систему? а также будет ли у меня доступ к переменным сеанса (созданным только один раз) на разных контроллерах в моем приложении?
Туто Пол Гаотингве 03
31
Вы можете хранить что угодно или любые данные любого типа в сеансе. После создания вы можете получить доступ к сохраненному в нем значению во всех представлениях и контроллерах. Также обратите внимание, что созданный сеанс доступен только для каждого пользователя и для каждого браузера. Это означает, что сеанс, созданный пользователем User1 с помощью Firefox, не может быть доступен одному и тому же пользователю с помощью IE. Есть вещи, которые вам не следует делать с сессией, например. НЕ храните на нем большие данные. Это может снизить производительность вашего сервера. Наконец, НЕ храните конфиденциальные данные в сеансе, такие как пароль или номер кредитной карты
Джоберт Энамно,
2
Еще раз спасибо! Где мне создать его, чтобы иметь к нему доступ через разные контроллеры?
Туто Пол Гаотингве 03
2
@JobertEnamno, безопасно ли хранить полученное значение, WebSecurity.CurrentUserIdчтобы оно не извлекалось из базы данных несколько раз (я обнаружил, что это очень дорого)?
Андрюс Нарушявичюс
2
Нет сеанса кросс-контроллера, поэтому, когда вы запрашиваете другой контроллер, например, из Account/LogOnв Home/Index, Session["FirstName"]это null. Разработчики должны создать родительский контроллер ( BaseController) и определить защищенное поле ( internal protected HttpSessionStateBase SharedSession), которое может отображать общую переменную сеанса во всех BaseController
субконтроллерах
63

Из-за того, что сеть не имеет состояния, сеансы также являются чрезвычайно полезным способом сохранения объектов в запросах путем их сериализации и сохранения в сеансе.

Идеальным вариантом использования этого может быть, если вам нужно получить доступ к регулярной информации в вашем приложении, чтобы сохранить дополнительные вызовы базы данных по каждому запросу, эти данные могут быть сохранены в объекте и десериализованы по каждому запросу, например:

Наш многоразовый сериализуемый объект:

[Serializable]
public class UserProfileSessionData
{
    public int UserId { get; set; }

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

Пример использования:

public class LoginController : Controller {

    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            var profileData = new UserProfileSessionData {
                UserId = model.UserId,
                EmailAddress = model.EmailAddress,
                FullName = model.FullName
            }

            this.Session["UserProfile"] = profileData;
        }
    }

    public ActionResult LoggedInStatusMessage()
    {
        var profileData = this.Session["UserProfile"] as UserProfileSessionData;

        /* From here you could output profileData.FullName to a view and
        save yourself unnecessary database calls */
    }

}

После того, как этот объект был сериализован, мы можем использовать его во всех контроллерах без необходимости его создания или повторного запроса в базе данных содержащихся в нем данных.

Внедрите объект сеанса с помощью инъекции зависимостей

В идеальном мире вы должны ` ` программировать интерфейс, а не реализацию '' и вводить свой сериализуемый объект сеанса в свой контроллер, используя выбранный контейнер Inversion of Control, например (в этом примере используется StructureMap, поскольку это тот, с которым я наиболее знаком ).

public class WebsiteRegistry : Registry
{
    public WebsiteRegistry()
    {
        this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());   
    }

    public static IUserProfileSessionData GetUserProfileFromSession()
    {
        var session = HttpContext.Current.Session;
        if (session["UserProfile"] != null)
        {
            return session["UserProfile"] as IUserProfileSessionData;
        }

        /* Create new empty session object */
        session["UserProfile"] = new UserProfileSessionData();

        return session["UserProfile"] as IUserProfileSessionData;
    }
}

Затем вы должны зарегистрировать это в своем Global.asax.csфайле.

Для тех, кто не знаком с инъекцией объектов сеанса, вы можете найти более подробное сообщение в блоге по этой теме здесь .

Слово предупреждения:

Стоит отметить, что количество сеансов должно быть сведено к минимуму, так как большие сеансы могут вызвать проблемы с производительностью.

Также рекомендуется не хранить в них конфиденциальные данные (пароли и т. Д.).

Джозеф Вудворд
источник
Но где бы вы поместили определение класса? Я все еще новичок во всем, но мне просто любопытно, как другие контроллеры увидят этот класс и узнают, что это такое. Вы просто добавляете его в верхнюю часть контроллера? Я думал о SessionStart в global.asax, я бы инициализировал вещи, но, возможно, это не лучший способ сделать это.
Shaun314
@ Shaun314 В идеале вы должны использовать контейнер IoC для внедрения объекта в ваш контроллер посредством внедрения зависимостей (см. Редактирование).
Джозеф Вудворд
1
Я сохраняю некоторую информацию о сеансе после входа пользователя в систему с использованием Identity 2. Я не могу получить эту информацию в других действиях и контроллерах, кроме первого действия, на которое я перенаправляю пользователя. Любая идея?
Акбари,
17

Вот как работает состояние сеанса в ASP.NET и ASP.NET MVC:

Обзор состояния сеанса ASP.NET

По сути, вы делаете это, чтобы сохранить значение в объекте Session:

Session["FirstName"] = FirstNameTextBox.Text;

Чтобы получить значение:

var firstName = Session["FirstName"];
Лениэль Маккаферри
источник
10
Сеанса кросс-контроллера не существует, поэтому, когда вы запрашиваете другой контроллер, например от Accountдо Home, Session ["FirstName"] имеет значение null. Разработчики должны создать BaseControllerи определить защищенное поле ( internal protected HttpSessionStateBase SharedSession), которое может отображать общую Sessionпеременную во всех BaseController
субконтроллерах
4
Умм, конечно есть? В контроллере есть переменная сеанса (базовый контроллер, предоставляемый MVC).
aeliusd
7
@Bellash это совершенно неверно. Сеансы доступны на всех контроллерах. Я просто установил Session ["test"] в HomeController, а затем прочитал его в моем AccountController.
niico 06
0

Вы можете хранить любые данные в сеансе, используя:

Session["VariableName"]=value;

Эта переменная будет длиться около 20 минут.

Улис
источник
-8

U может хранить любое значение в сеансе, например Session ["FirstName"] = FirstNameTextBox.Text; но я предлагаю вам использовать как статическое поле в модели, присвоить ему значение, и вы можете получить доступ к этому значению поля в любом месте приложения. Вам не нужна сессия. сеанса следует избегать.

public class Employee
{
   public int UserId { get; set; }
   public string EmailAddress { get; set; }
   public static string FullName { get; set; }
}

на контроллере - Employee.FullName = "ABC"; Теперь вы можете получить доступ к этому полному имени в любом месте приложения.

Мукул Шарма
источник
10
Хранение данных в статических полях, особенно пользовательских данных, таких как имя сотрудника, вызовет серьезные проблемы в многопользовательских средах. Когда два разных пользователя вошли в систему, они увидят один и тот же адрес Employee.EmailAddress, поскольку статическое поле в Employee одинаково для каждого экземпляра.
Gökçer Gökdal 08