我有几个.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
和会话状态是一个坏主意?
答案 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的常见问题是:
这就是说,拥有依赖于会话的有状态服务是糟糕的设计。在您显示的示例中,这是一个ASMX WebService,它取决于ASP.NET会话状态,这意味着客户端应该传递cookie以调用此服务。有状态的服务也难以扩展。