Я пишу веб-приложение, которое позволит пользователю просматривать несколько веб-страниц на веб-сайте с определенными запросами. Вся информация, которую вводит пользователь, будет храниться в объекте, который я создал. Проблема в том, что мне нужен этот объект для доступа с любой части веб-сайта, и я действительно не знаю, как это сделать. Я знаю, что одним из решений является использование переменных сеанса, но я не знаю, как их использовать в asp.net MVC. И где я могу объявить переменную сеанса? Есть ли другой способ?
Переменные сеанса в ASP.NET MVC
Ответ 1
Я бы подумал, что вам захочется подумать о том, действительно ли вещи относятся к состоянию сеанса. Это то, что я нахожу себе время от времени, и это хороший строго типизированный подход ко всему, но вы должны быть осторожны, когда вкладываете вещи в контекст сессии. Не все должно быть там только потому, что оно принадлежит определенному пользователю.
в global.asax подключить событие OnSessionStart
void OnSessionStart(...)
{
HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
}
Из любого места в коде, где свойство HttpContext.Current!= null, вы можете извлечь этот объект. Я делаю это с помощью метода расширения.
public static MySessionObject GetMySessionObject(this HttpContext current)
{
return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
}
Таким образом вы можете в коде
void OnLoad(...)
{
var sessionObj = HttpContext.Current.GetMySessionObject();
// do something with 'sessionObj'
}
Ответ 2
Ответ здесь правильный, однако я старался реализовать его в приложении ASP.NET MVC 3. Я хотел получить доступ к объекту Session в контроллере и не мог понять, почему я продолжал получать "экземпляр, не установленный в экземпляр ошибки объекта". Я заметил, что в контроллере, когда я пытался получить доступ к сеансу, выполнив следующее, я продолжал получать эту ошибку. Это связано с тем, что this.HttpContext является частью объекта Controller.
this.Session["blah"]
// or
this.HttpContext.Session["blah"]
Однако, я хотел, чтобы HttpContext был частью пространства имен System.Web, потому что это тот, который предлагает вышеприведенный ответ в Global.asax.cs. Поэтому я должен был явно сделать следующее:
System.Web.HttpContext.Current.Session["blah"]
это помогло мне, не уверен, что я сделал что-то, что не было М. О. здесь, но я надеюсь, что это поможет кому-то!
Ответ 3
Поскольку мне не нравится видеть "HTTPContext.Current.Session" о месте, я использую одноэлементный шаблон для доступа к переменным сеанса, он дает вам простой доступ к строго типизированному пакету данных.
[Serializable]
public sealed class SessionSingleton
{
#region Singleton
private const string SESSION_SINGLETON_NAME = "Singleton_502E69E5-668B-E011-951F-00155DF26207";
private SessionSingleton()
{
}
public static SessionSingleton Current
{
get
{
if ( HttpContext.Current.Session[SESSION_SINGLETON_NAME] == null )
{
HttpContext.Current.Session[SESSION_SINGLETON_NAME] = new SessionSingleton();
}
return HttpContext.Current.Session[SESSION_SINGLETON_NAME] as SessionSingleton;
}
}
#endregion
public string SessionVariable { get; set; }
public string SessionVariable2 { get; set; }
// ...
то вы можете получить доступ к своим данным из любого места:
SessionSingleton.Current.SessionVariable = "Hello, World!";
Ответ 4
Если вы используете asp.net mvc, вот простой способ получить доступ к сеансу.
От контроллера:
{Controller}.ControllerContext.HttpContext.Session["{name}"]
Из представления:
<%=Session["{name}"] %>
Это определенно не лучший способ получить доступ к вашим переменным сеанса, но это прямой маршрут. Поэтому используйте его с осторожностью (желательно во время быстрого прототипирования) и используйте Wrapper/Container и OnSessionStart, когда это станет подходящим.
НТН
Ответ 5
Ну, ИМХО..
- никогда не ссылайтесь на сеанс внутри вашей главной страницы /
- минимизируйте использование сеанса. MVC предоставляет TempData obj для этого, что в основном представляет собой сеанс, который живет для одной поездки на сервер.
Что касается № 1, у меня есть строго типизированный Master View, у которого есть свойство для доступа к тому, что представляет объект Session... в моем примере сильно типизированный Master View является общим, что дает мне некоторую гибкость в отношении напечатанные страницы просмотра
ViewMasterPage<AdminViewModel>
AdminViewModel
{
SomeImportantObjectThatWasInSession ImportantObject
}
AdminViewModel<TModel> : AdminViewModel where TModel : class
{
TModel Content
}
а затем...
ViewPage<AdminViewModel<U>>
Ответ 6
Хотя я не знаю о asp.net mvc, но это то, что мы должны делать на обычном веб-сайте .net. Он также должен работать для asp.net mvc.
YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null){
obj=new YourSessionClass();
Session["key"]=obj;
}
Вы бы поставили это внутри метода для легкого доступа. НТН
Ответ 7
Есть 3 способа сделать это.
Вы можете напрямую получить доступ к
HttpContext.Current.Session
Вы можете Mock
HttpContextBase
Создайте метод расширения для
HttpContextBase
Я предпочитаю третий способ. Эта ссылка является хорошей ссылкой.
Ответ 8
Отличные ответы от ребят, но я бы предостерег вас от того, чтобы всегда полагаться на Сессию. Это быстро и легко сделать, и, конечно, это сработает, но не будет здорово во всех случаях.
Например, если вы используете сценарий, в котором ваш хостинг не разрешает использование сеанса, или если вы находитесь в веб-ферме или в примере общего приложения SharePoint.
Если вы хотите другое решение, вы можете посмотреть, как использовать контейнер IOC Container, например Castle Windsor, создавая класс поставщика в качестве обертки, а затем сохраняя один экземпляр вашего класса с использованием каждого запроса или стиля сеанса в зависимости от ваших требований.
IOC гарантирует, что один и тот же экземпляр будет возвращен каждый раз.
Сложнее да, если вам нужно простое решение, просто используйте сеанс.
Ниже приведены примеры реализации ниже.
С помощью этого метода вы можете создать класс поставщика по строкам:
public class CustomClassProvider : ICustomClassProvider
{
public CustomClassProvider(CustomClass customClass)
{
CustomClass = customClass;
}
public string CustomClass { get; private set; }
}
И зарегистрируйте что-то вроде:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ICustomClassProvider>().UsingFactoryMethod(
() => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
}
Ответ 9
Вы можете использовать ViewModelBase в качестве базового класса для всех моделей, этот класс позаботится о выводе данных из сеанса
class ViewModelBase
{
public User CurrentUser
{
get { return System.Web.HttpContext.Current.Session["user"] as User };
set
{
System.Web.HttpContext.Current.Session["user"]=value;
}
}
}
Вы можете написать метод расширения для HttpContextBase для обработки данных сеанса
T FromSession<T>(this HttpContextBase context ,string key,Action<T> getFromSource=null)
{
if(context.Session[key]!=null)
{
return (T) context.Session[key];
}
else if(getFromSource!=null)
{
var value = getFromSource();
context.Session[key]=value;
return value;
}
else
return null;
}
Используйте это, как показано ниже в контроллере
User userData = HttpContext.FromSession<User>("userdata",()=> { return user object from service/db });
Второй аргумент необязателен, он будет использоваться для заполнения данных сеанса для этого ключа, когда значение не присутствует в сеансе.
Ответ 10
Мой способ доступа к сеансам - написать вспомогательный класс, который инкапсулирует различные имена полей и их типы. Надеюсь, этот пример поможет:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;
namespace dmkp
{
/// <summary>
/// Encapsulates the session state
/// </summary>
public sealed class LoginInfo
{
private HttpSessionState _session;
public LoginInfo(HttpSessionState session)
{
this._session = session;
}
public string Username
{
get { return (this._session["Username"] ?? string.Empty).ToString(); }
set { this._session["Username"] = value; }
}
public string FullName
{
get { return (this._session["FullName"] ?? string.Empty).ToString(); }
set { this._session["FullName"] = value; }
}
public int ID
{
get { return Convert.ToInt32((this._session["UID"] ?? -1)); }
set { this._session["UID"] = value; }
}
public UserAccess AccessLevel
{
get { return (UserAccess)(this._session["AccessLevel"]); }
set { this._session["AccessLevel"] = value; }
}
}
}