使用ApiController的会话状态

时间:2013-01-10 07:09:23

标签: asp.net-mvc-4 controller session-state

我希望在我的ApiController(MVC4)中拥有自己的AppContext。

应该像

public class TestController : BaseApiController
{
    [HttpGet]
    public IEnumerable<TestVM> GetAll()
    {
        // the test service is injected with SimpleInjector
        return _testService.GetAll(**base.AppContext**);
    }
}

但是ApiController无法访问Session。 是否有任何解决方案来“激活”特定键的会话(因为我不想要整个会话)? 或者您有任何其他想法(缓存或cookie)?

这是BaseApiController

public abstract class BaseApiController: ApiController
{
    public IAppContext AppContext
    {
        get { return SessionState.AppContext; }
    }
}

这是我的IAppContext(将来会有更多属性)

public interface IAppContext
{
    IIdentity User { get; }

    /// <summary> Gets the user id. </summary>
    /// <value>The user id.</value>
    int IdUser { get; }
}

这里是在web.config

中注册的应用程序模块
public class ApplicationModule : IHttpModule
{
    // ...
    SessionState.AppContext = _appContext.InitializeNew(
        HttpRuntime.AppDomainAppPath, languages);
    // ...
}

SessionState类获取AppContext

public class SessionState : BaseSessionVariables
{
    public static IAppContext AppContext
    {
        get { return SessionState.Get<IAppContext>("AppContext"); }
        set { SessionState.Set("AppContext", value); }
    }
}

这里是BaseSessionVariables类

public static HttpSessionState GetSession()
{
    return HttpContext.Current.Session;
}

protected static T Get<T>(string key) where T : class
{
    var session = BaseSessionVariables.GetSession();

    if (session == null)
    {
        throw new Exception("No session");
    }
    return (session[key] as T);
}

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

看看下面的实现。它应该让你朝着正确的方向前进。

更新了IAppContext - 添加了Setter

public interface IAppContext
{
    IIdentity User { get; set; }

    /// <summary> Gets the user id. </summary>
    /// <value>The user id.</value>
    int IdUser { get; set; }
}

更新的基本控制器 - 在OnActionExecuting方法中实例化一个新的AppContextImplemenation

public abstract class BaseApiController: ApiController
{
    public IAppContext AppContext {get; set;}

    protected override void OnActionExecuting(
        ActionExecutingContext filterContext)
    {
        AppContext = new AppContextImplementation();
    }
}

New Class - 实现IAppContext并包装HttpContext会话。为了进行测试,您可以创建一个TestAppContextImplementation,它不依赖于Session,而是依赖于其他一些内存存储机制。

public class AppContextImplementation : IAppContext
{
    public IIdentity User
    { 
        get { return HttpContext.Current.Session["User"] as IIdentity; }
        set { HttpContext.Current.Session["User"] = value; }
    }

    int IdUser
    { 
        get { return Convert.ToInt32(Session["IdUser"]); }
        set { Session["IdUser"] = value; }
    }
}

答案 1 :(得分:-1)

对于ApiControllers,请自己构建一个DelegatingHandler并将所有好处推送到request.Properties。无论您是在测试还是在线运行,您都可以从您的请求中检索它们。这样做的好处是,您可以在Controller中对Session进行零依赖。

的MessageHandler

public class ContextHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        // get the goodies to add onto the request
        var goodies = /* call to goodieGoodieYumYum */


        // add our goodies onto the request
        request.Properties.Add(Constants.RequestKey_Goodies, goodies);

        // pass along to the next handler
        return base.SendAsync(request, cancellationToken);
    }
}

控制器操作

var goodies = (List<Goodie>)Request.Properties[Constants.RequestKey_Goodies];