在SharePoint Web应用中访问Session对象时发生System.NullReferenceException异常

我们有个客户在SharePoint Web应用中集成自定义的代码到时,经常遇到System.NullReferenceException异常。通常来说,如果程序配置成了Web Garden或者非Session Affinity的负载均衡,现象容易出现。 但这次情况有所不同。 通过.NET异常捕获,发现它是在访问Session对象的时候发生的。 000007ff`00fc2067 e8d4bb58ec call system_web_ni+0x25dc40 (000007fe`ed54dc40) (System.Web.HttpContext.get_Current(), mdToken: 060003c6) 000007ff`00fc206c 803800 cmp byte ptr [rax],0 000007ff`00fc206f 488bc8 mov rcx,rax 000007ff`00fc2072 e8511453ec call system_web_ni+0x2034c8 (000007fe`ed4f34c8) (System.Web.HttpContext.get_Session(), mdToken: 060003e2) 000007ff`00fc2077 48bb98c6a37f01000000 mov rbx,17FA3C698h 000007ff`00fc2081 488b13 mov rdx,qword ptr [rbx] >>> 000007ff`00fc2084 803800 cmp byte ptr [rax],0 代码片段如下: HttpContext.Current.Session[“userdata”] = “123”; 为了解决这类问题,我们在Web.Config中显式地将EnableSessionState设为True。 <%@…

0

在预编译 (Pre-Compiled) 的ASP.NET应用中页面设置失效的问题

我的客户有一个验证视图(viewstate)MAC失败的问题。作为应急措施,他想在找出最终的解决方案之前,禁用视图MAC验证。然而当他在配置文件中添加了如下的设置后,还是有问题。 <pages validateRequest=”false” enableEventValidation=”false” enableViewStateMac=”false” viewStateEncryptionMode=”Never”> 客户的应用是一个预编译 (Pre_compiled) 的ASP.NET应用,且可更新(updateable)的选项被禁用。看了由编译器通过上述设置生成的代码后,我们发现这些设置是硬编码。所以这意味着仅仅简单地在web.config里添加上述设置,并不会影响预编译的应用。为了使其生效,必须重新编译整个应用。  [DebuggerNonUserCode] private void __BuildControlTree(default_aspx __ctrl) { __ctrl.EnableViewStateMac = false; __ctrl.EnableEventValidation = false; __ctrl.ViewStateEncryptionMode = ViewStateEncryptionMode.Never; 这是一个By-Design的行为。 ASP.NET预编译概述如下: http://msdn.microsoft.com/en-us/library/bb398860.aspx Wei Zhao from AGPC DSI Team  

0

IE访问IIS7.5架设的需Windows认证的网站时出现不停弹框的问题

这是一个安装了IIS的Windows 2008系统,它已运行了一些Sharepoint站点。这些Sharepoint站点使用Windows认证,且他们都正常运行。 现在在此服务器上部署了一个新的Web站点,并启用了Windows认证(采用内核态),但当通过HTTP://MyWebServer:8080或HTTP://MyWebServer.MyDomain.com:8080访问此站点时,IE会不停地请求认证。 首先,我们用域认证信息(domain credentials)测试了基本认证(basic authentication),它是成功的。然后我们启用了登陆事件的审查(audit)功能;不幸的是,不管是否成功进入了Web站点,我们都没能发现任何登陆事件的记录。 为了找出与此有关的更多信息,我们启用了IIS FREB跟踪功能,发现“IIS Web Core”设置了401状态,其错误信息是“拒绝访问”。 现在,我们不得不回来看看对Kerberos纠错最有用的信息——网络监视跟踪记录。从捕获的信息来看,我们确认了Kerberos错误是KRB_AP_ERR_MODIFIED。 有两个引发该错误的常见原因: 1. 错误的DNS设定 2. 客户端发送的ticket被用不同的密钥加密/解密。 我们用netmon确认了DNS的运行在意料之中。我们用Ldp工具审查SPN,当查询SPN时得到了如下的结果 Dn: CN=MyWebServer,…….. …… servicePrincipalName (11): …. HOST/MyWebServer.MyDomain.com; HOST/MyWebServer; …. Dn: CN=SPS_Service_Account……. …. servicePrincipalName (18): …… HTTP/ MyWebServer.MyDomain.com; HTTP/ MyWebServer; …… 我们能看到,HTTP/MyWebServer是SharePoint服务里注册的账号(被用来运行SharePoint应用池),运行在内核态认证的IIS 7以上服务器是不需要它的。然后回IIS MMC查看,我们发现所有SPS站点都采用用户态的Windows认证,它需要把SPN账号注册到应用池认证中。这就是SPS站点以Windows认证的方式运行的原因。 新添加的站点使用用户态Windows认证,需要在机器账号中注册的SPN的账号。这与SharePoint站点产生了冲突。 这解释了为何我们得到了KRB_AP_ERR_MODIFIED错误。当IE访问http://MyWebServer:8080时,请求HTTP/MyWebServer的ticket,它被注册在SharePoint服务的账号里。IE把该ticket传递给Web服务器。在服务器端,IIS尝试使用机器账号对该ticket解密。这必然会失败,因为它被另一个密钥解密。 为了解决此问题: 1. 我们给新添加的站点,如MySite,使用host头,将其加到站点绑定中。 2.注册SPN HTTP/MySite的本机账号 3.现在,我们使用http://MySite访问此Web站点。 随后,我们做以下SPN的配置: MyWebServer: HTTP/MySite HTTP/MySite.MyDomain.com HOST/ MyWebServer HOST/…

0

如何解决请求超时的HttpException异常 (ASP.NET 2.0 32-bit)

注意:下列的步骤适用于ASP.NET 2.0(32 bit) 。没有测试过其他版本的ASP.NET。 症状 ======== 应用事件记录里可能出现下方的警告文字: 这种问题基本上发生在当ASP.NET的服务器端执行请求的时间超过所允许的最大时间之时。 最大超时时间可以在配置文件的httpRuntime元素的executionTimeout属性中设置。(在.Net 2.0中,默认值是110秒 如何重现 =============== 创建一个ASPX页面,命名为sleep.aspx。它将睡眠20秒: <%@ Page Language=”C#” %> <%@ import Namespace=”System.Diagnostics” %> <script runat=”server”> protected void Page_Load(object sender, EventArgs e) { DateTime time = DateTime.Now; Response.Write(String.Format(“Time: {0}:{1}:{2}”, time.Hour, time.Minute, time.Second) + “\tCurrent process: ” + Process.GetCurrentProcess().Id.ToString()); Response.Write(“<BR>”); Response.Write(String.Format(“This application is running in {0}”, System.Environment.Version.ToString())); System.Threading.Thread.Sleep(20000); }…

2

为什么第一次访问ASP.NET应用会很慢

  问题现象 ========== ASP.NET页面第一次访问的时候很慢,时间可以持续几十秒到几分钟   问题原因 ========== 当程序里面需要调用到一些Authenticode Signed的.NET Assembly的时候,它需要连接到外网来验证数字证书。当服务器是无法连接到外网时,这个校验证书的过程需要等到timeout之后才会结束。   解决办法 ========== 建议采用以下方法中的任何一种 让您的服务器能连接到外网 参考http://support.microsoft.com/kb/936707的方法来禁止证书的验证过程 请同时在以下两个aspnet.config文件中加入以下内容。 C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet.config C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet.config <?xml version=”1.0″ encoding=”utf-8″?> <configuration>         <runtime>                         <generatePublisherEvidence enabled=”false”/>         </runtime> </configuration> 或者参考http://blogs.msdn.com/b/tom/archive/2008/10/28/web-site-stops-responding-for-15-25-seconds.aspx对″Network Service”帐号下运行的所有程序禁止证书检查 导入以下注册表键值并重起IIS服务 Windows Registry Editor Version 5.00 [HKEY_USERS\S-1-5-20\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing] “State”=dword:00023e00   详细分析 ========== 这个时候如果我们抓取一个hang dump的话,页面所对应的managed callstack往往如下,很明显它正在加载一个Assembly 0:022> !CLRStack OS Thread Id: 0xeb4…

0

由string.IndexOf引起的ASP.Net应用挂起

最近有一个有趣的案例,我们发现String.IndexOf会造成ASP.Net应用挂起。   问题描述: 通常这种ASP.Net应用程序将挂起,因此IIS工作进程需要重新启动使得应用程序能够正常运行。即使当负载比较低的时候也会发生这种情况。   排除故障: 像以前一样,我们抓获挂起dump,我们可以看到几乎请求都会被GC阻止。下面是一个示例调用堆栈。   ntdll!ZwWaitForSingleObject kernel32!WaitForSingleObjectEx mscorwks!CLREventWaitHelper mscorwks!CLREvent::WaitEx mscorwks!SVR::gc_heap::wait_for_gc_done mscorwks!SVR::gc_heap::try_allocate_more_space … Some customer code here … System_Web_ni!System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32)   但是,如果去查看一下GC线程,发现他们根本不在GC状态。之后我们发现线程48禁用了PreEmptive GC,不允许GC来暂停它。所以GC必须等到这个线程结束。   PreEmptive Lock ID OSID ThreadOBJ State GC GC Alloc Context Domain Count APT Exception 24 1 1e48 000000000015f280 1808220 Enabled 00000000902c9e50:00000000902c9e70 00000000001bbbe0 1 MTA (Threadpool Worker) …………………… 48 8…

0

当一个进程中加载多个.NET Runtime的时候如何在托管调试中加载指定的mscordacwks.dll

当多个.NETRuntime加载在一个目标进程或一个dump文件中,例如:  0:030> lm  start end module name  00000000’1b6d0000 00000000’1b9ba000 System_Data (deferred) …  000007fe’f3e60000 000007fe’f47c5000 clr (deferred) …  000007fe’f9880000 000007fe’fa230000 mscorwks (deferred) …  0:030> lmvm clr  start end module name  000007fe’f3e60000 000007fe’f47c5000 clr (deferred) Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll  Image name: clr.dll  ……  CompanyName: Microsoft Corporation  ProductName: Microsoft® .NET Framework  InternalName: clr.dll  OriginalFilename: clr.dll  ProductVersion: 4.0.30319.1  FileVersion: 4.0.30319.1…

0

高性能ASP.NET应用程序(2)——ASP.NET缓存简介

上次我们介绍了ASP.NET应用程序状态管理方面的一些内容。今天,我们将继续上次关于编写高性能ASP.NET程序的话题,探讨一下ASP.NET的缓存机制。在编写ASP.NET应用程序时,能否有效地利用缓存对于程序的响应时间和资源管理方面至关重要。这一次,我们将讨论以下四个部分:     1)正确地使用缓存API     2)利用输出缓存和片段缓存     3)缓存在Web Farm中的应用     4)有效应用缓存方面的一些建议     缓存API非常简单并易于使用,但仍然有一些情况下,你应该避免使用它们。例如,如果你要缓存的数据是特定于某个用户的,那么还是保存在会话状态中为好。如果某些数据更新非常频繁,那么这些数据在缓存中也不会被保存很久,因此缓存这样的数据对性能提高没有任何好处。我想提请您特别注意一下的是AddValidationCallback。这个函数在当你想为不同的客户定制缓存数据时是非常有用的。下面的代码演示了如何使用AddValidationCallback来依据输入的查询字符串自定义请求的处理过程的。 <script language=”c#” runat=”server”>      HttpContext ctx = HttpContext.Current;    static string validationstate;      public void Page_Load()    {       Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(ValidateCache), null);       ctx.Response.Write(“”);    }      public static void ValidateCache(HttpContext context, Object data, ref HttpValidationStatus status)    {      …

0

高性能ASP.NET应用程序(1)——优化状态管理

         今天我们来聊一下在编写ASP.NET应用程序的时候如何优化状态管理。我相信绝大多数的ASP.NET开发人员或多或少的都会对使用ASP.NET的状态有所了解。在本文中,我们不会把如何使用ASP.NET的状态作为重点,而更侧重于讨论如何更加有效率和有效果的管理ASP.NET的状态。Web应用程序为状态管理提出了一些具体的挑战,尤其是Web场/园的情形。您就状态存储的位置和方法所作出的决定对您的应用程序的性能和扩展性将会产生巨大的影响。          总的来说,ASP.NET中有3种状态:应用程序状态、会话状态和视图状态。他们分别需要在不同的情形下使用。应用程序状态应用于所有的用户和会话。而会话状态用于存储单个用户的状态。在这里单个用户可以理解为来自同一个浏览器的请求。视图状态用于存储单个页面的状态信息,就像在某个具体网页的控件中包含的内容。归结起来有2种状态管理指南:1)在客户端上存储简单的状态;2)考虑序列化带来的开销。对于第一点,当视图状态不可用时您可以考虑利用客户端cookie、查询字串或者隐藏控件。考虑到状态的序列化,请确保只在必要时才进行存储,并且倾向于存储简单的类型(约15%到25%的性能影响)而非复杂的对象(可能会有更大的影响)。          现在我们来分别谈一下怎样最优化应用程序状态、会话状态和视图状态管理。          应用程序状态管理技巧: 1. HttpApplicationState VS 静态属性:您应该避免在应用程序对象中存储数据。取而代之的是,您可以使用应用程序类的静态成员。您可以由此获得性能提升因为访问静态成员会比访问应用程序对象快得多。一个例子是: <% private static string[] _states[]; private static object _lock = new object(); public static string[] States {   get {return _states;} } public static void PopulateStates() {   //ensure this is thread safe   if(_states == null)   {     lock(_lock)     {…

0