为什么在WebAPI中访问会话状态和HttpContext被认为是错误的设计?

时间:2014-01-21 15:40:11

标签: asp.net azure

我有几个.asmx Web服务,我想升级到WebAPI。这些Web服务看起来像这样:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class TheWebService : System.Web.Services.WebService {

   [WebMethod(EnableSession = true)]
   public string SomeMethod(string SomeInput)
   {
       MySessionModel TheSession = HttpContext.Current.Session["UserSession"] as MySessionModel;

       return SomeClass.SomeMethod(SomeInput, TheSession);
   }
}

基本上,我有一个单页面的应用程序。我正在使用Forms Auth登录并将用户重定向到他们的“个人资料”,然后,从该页面,该应用程序使用Web服务与服务器进行通信。 Web服务只返回原始字符串,因此我不需要在Web服务级别进行序列化。目前,该应用程序托管在IIS中,很快我就会将其部署到azure中。

我在网上浏览过,有几篇帖子暗示使用会话状态和HttpContext设计不好。在这种情况下,为什么使用HttpCurrent和会话状态是一个坏主意?

2 个答案:

答案 0 :(得分:4)

使用ASP.NET Session没有任何天生的错误,只要你不将它用作任何旧数据的全能篮子。例如,购物车不属于Session:它们属于购物车持久性组件。

此外,我怀疑此问题上Azure标记的原因,如果您在负载均衡的环境(如Azure云服务)中运行,则需要使用外部会话提供程序,如SQL数据库或共享缓存。使用进程内会话提供程序(默认值)将导致非常奇怪的,通常无法产生的错误,因为用户在具有不同会话副本的不同服务器之间切换。

对于HttpContext.Current,对于Web API,控制反转,依赖注入和简单可测试性等内容非常重要。该服务的干净,可测试的Web API版本可能如下所示:

public class TheWebService : ApiController {

    private readonly IUserSession _userSession;

    public TheWebService(IUserSession userSession)
    {
        _userSession = userSession;
    }
    public string SomeMethod(string SomeInput)
    {
        MySessionModel TheSession = _userSession.Get();
        return SomeClass.SomeMethod(SomeInput, TheSession);
    }
}

public interface IUserSession
{
    MySessionModel Get();
}

你仍然可以在这样的课程中使用 HttpContext.Current.Session["UserSession"]

public class CurrentContextUserSession : IUserSession
{
    public MySessionModel Get()
    {
        return HttpContext.Current.Session["UserSession"] as MySessionModel;
    }
}

然后,您将使用Unity或Ninject等IoC容器将CurrentContextUserSession设置为IUserSession的实现,以便在构造TheWebService的实例时使用Web API。但是在编写测​​试时,可以使用IUserSession的模拟或存根实现,它不依赖于HttpContext.Current

答案 1 :(得分:2)

在您的具体示例中,您只在WebMethod中使用Session,这很好,因为它已经耦合到ASP.NET但很多人倾向于在其应用程序的其他层使用它,这是一个非常糟糕的设计。

在这些图层中使用HttpContext.Current的常见问题是:

  1. 代码不能单独进行单元测试
  2. 代码紧密耦合到ASP.NET上下文
  3. 这就是说,拥有依赖于会话的有状态服务是糟糕的设计。在您显示的示例中,这是一个ASMX WebService,它取决于ASP.NET会话状态,这意味着客户端应该传递cookie以调用此服务。有状态的服务也难以扩展。