我在完整IIS模式下运行Azure Web角色。请求已获得custom basic authentication授权。
我有MyAssembly.CustomIdentity
类继承自System.Security.Principal.GenericIdentity
。当调用HttpApplication.AuthenticateRequest
处理程序(上面链接中的OnEnter()
代码)时,它会执行检查,然后创建MyIdentity.CustomIdentity
的实例并将其分配给HttpContext.Current.User
。然后,一个实际的ASP.NET请求处理程序获取该对象,并可以使用它来查找它的用户。
现在,当IIS在NETWORK SERVICE
帐户下运行时,默认配置中的所有内容都可以正常运行。在角色启动期间,我在本地用户下重新启动IIS应用程序池(以授予它额外的权限)。现在甚至以下代码
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
bool isAvailable = Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsAvailable;
}
}
将抛出各种异常。首先它说它无法序列化我的CustomIdentity
类(我通过添加Serializable
属性修复),然后它说它无法加载MyAssembly
程序集(我通过处理{修复{1}}事件)。
我不知道为什么序列化开始了?为什么在本地用户下运行应用程序池并调用那些简单的代码会突然触发序列化?
答案 0 :(得分:4)
编辑重新阅读您的问题,我不太确定这是问题所在。我将它留在这里,因为我花了5分钟写它,这是有用的信息:)如果你正在编写网络应用程序,你需要了解会话状态和存储选项!
<小时/> 正如Daniel Powell所说,你很可能在会话状态中存储了一个对象实例。
ASP.NET应用程序有3种标准模式用于存储会话状态。 InProc
(进程内)将其存储在内存中,因此不需要序列化。 StateServer
或SqlServer
将尝试将会话状态分别序列化为ASP.NET状态服务器或SQL服务器。
要确认这是问题,您需要检查web.config文件中mode
元素的sessionState
属性。
<sessionState mode="InProc|SqlServer|StateServer" />
如果您使用的是SQL Server或State Server,那么您的应用程序将在每个请求结束时序列化整个会话状态。你有几个选择:
将会话状态更改为InProc。这将阻止序列化,但您将无法使用负载平衡环境。此外,如果您的应用程序重新启动,则所有用户都将丢失其会话(因为它保存在内存中)。
停止将此对象放入会话中。如果你不需要将这个对象存储在Session中,那就不要了!问题解决了。
通过实现ISerializable,使对象及其任何子元素可序列化。如果对象使用“实时”元素(如数据库连接等)
答案 1 :(得分:1)
对这个答案要谨慎,因为我不能确定它是好的答案。
首先,我假设你没有设置类似sql会话管理的东西,你唯一改变的是运行IIS的用户。
你观察到两种现象:
由于您的appdomain已经加载了程序集,因此可以安全地假设该异常是由另一个AppDomain引发的。如果它被另一个Appdomain抛出,可能是因为此AppDomain正在尝试反序列化您的自定义对象。 (在另一个例外证明之前,它已被序列化。)
行。现在即使IIS在本地用户下运行,角色环境也不是。此服务随Azure OS一起安装,您无法选择其运行的用户(事实上您可能会这样做,但我不会)
我认为,为了从RoleEnvironnement获取信息,Azure运行时能够使用两个代码路径:
总而言之,我当然不知道为什么Azure运行时希望在不同的AppDomain之间移动您的用户,但它可能正是这样做的。
答案 2 :(得分:0)