杂感

  如果说被真实的生活所欺骗了,
  其实欺骗着不过是自己,
  
  很多东西都已经改变了,
  只是学校和家庭构造了理想国。
  难以接受的现实,
  无力改变,
  
  于是开始尝试去适应,
  
  遭遇的只是抵触,
  面对的只是挣扎,
  
  也许这就是所谓的不适。
  
  很久以前的梦在眼前幻灭,
  开始很努力的让自己去接收眼前的一切,
  
  当接受时发现自己带上了面具。
  历经风雨,岁月侵蚀。
  
  突然有一天发现自己原来的面目已经模糊,
  于是开始找寻原来的影子,
  可惜到头来只是徒劳。
  
  因为原来的东西,早已被侵蚀,破败。
  
  留下的只是一局世俗的皮囊。
  当一切光环和饰品从上面挪去,
  
  他开始变得丑陋,令人厌恶,
  他真的丑陋而又令人厌恶么?
  
  也许你自己也无法确定,
  人们说它是美的,
  于是它就变成了美的。
  
  挣扎,在茫茫的泥泞中前行。

moss2007里面的BDC和WebService

  

对于moss2007里面的BDC这一块的内容,是新加进来的特性。这块功能十分类似于java里面的ORM,当然实现上面肯定是有质的区别。Bdc提供了一种数据共享的业务,为连接后台和表层业务数据建立了桥梁。实际上bdc为上层应用提供服务,实例化以后其实就是数据实体,简单的说就是Entity,我们不用担心bdc如何提供的这些实体,因为很多东西都已经在LobSystem里面处理了。只需要调用就可以,并且这些实体可以运用到各种Web Parts里面,成为共享的数据之一。

  

对于实体的描述,在BDC里面实际上是通过xml语言来进行的。

  

每一个实体,里面可以包含诸多东西,具体的大家可以看sdk里面的那张实体描述的图。在entity节里面大家可以发现method,identifier,property等节,他们都描述了实体是一个什么样的,即实体的方法,类型等。这里我只能粗略的说下我的一些经验,对于每一个方法群,实体必须要有一个方法的实例:即MethodInstance,只有这样实体才能调用方法的实例来获取数据。同样在方法里面可以定义你自己的数据筛选器,描述节为FilterDescription。利用BDC可以采用两种方式来获取数据,一种是采用web Service,一种是采用传统的ADO。在LobSystem里面提供两种配置,一个是采用WebServiceProxyNamespace,一个是采用RdbConnection。分别对应web Serviceado。这里不得不说一下,在moss里面的web service是托管的,所以在moss里面部署的Web Service必须采用特殊的格式。即:wsdl,disco文件必须做相应的更改。详细的一些步骤这里就不再说明,sdk里面有详细的部署方法。

  

每一个entity来说,必须有相应的方法名,数据名称,变量的描述,自定义类型的描述必须引入相应的类型。所有的parameter 的描述都是通过TypeDescriptor节来描述的,并且这些描述节可以嵌套。这样无论多复杂的parameter都可以被嵌套按层次描述出来。对于描述出来的方法,必须有相应的methodInstance,一个method可以有多个instance,但不能没有。

  

先说RdbConnection这种方式,也就是采用LobSystem里面自带的ADO引擎,首先我们必须定义采用引擎的数据提供类型,数据库类型,数据库名字等一系列的属性的定义,这些定义是在LobSystemInstance节里面描述的,其实这样做起来十分像java里面配置Hibernate里面的ORM后台数据库的配置节,其实这一套体系还是和java十分类似,由于看不到源代码,但是采用的设计模式应该差不多,同样也有连接池来维护一定数量的连接。对于数据的读取,这一块采用的主要是这两个接口,一个是IDataReader,IDataRecord,对于Entity的存放,采用的接口是IEntityInstanceEnumeator,IEntityInstance。前面二个接口是用来和数据库交互的,后面两个接口是用来和Entity交互的。对于后面两个接口,明眼人一下就可以看出来,一个是多条记录的枚举器,一个是单条记录。Sdk上面有几个画的很漂亮的图,因为我这里图片不好上传,传了还容易失效,所以就不贴图了(偷懒!!)。

  

再来说web service,BDC里面可以直接调用web service来创建自己的实体方法,我们所需要做的,只是在实体描述文件里面描述相应的web Service方法就可以了。这样我们就可以导入自己的实体,并且实体的数据是从网络上获得的。SDK有一个亚马逊的调用Web Service的例子,我没有做通,因为登陆采用的是pass through方式,那个代理服务器的地址一直没找到(如果有知道的,希望告知,万分感激!!!)。个人只是自己写一个调本地数据库web Service,然后自己写了一个entity的描述文件导入到了里面。这里有二个值得注意的地方,一个是对于Web Servicemoss里面的部署,一个是添加到web parts里面显示,对于数据库权限的控制。第一个问题只要细心的一般都可以搞定,部署在_layouts里面的Web Service通过moss托管,配置文件需要做相应的更改,实际上就是把soap里面的搜索地址更改了一下,具体的是这样改的:

  

<>xml version=1.0 encoding=utf-8?>

  

这个描叙需要改为:

  

<%@ Page Language="C#" Inherits="System.Web.UI.Page" %>

  

<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

  

<%@ Import Namespace="Microsoft.SharePoint.Utilities" %>

  

<%@ Import Namespace="Microsoft.SharePoint" %>

  

<% Response.ContentType = "text/xml"; %>

  

实际上就是把原来的纯xml变换成为一个page来解析。并且这个页面的解析是通过moss处理的,

  

<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request) + "?wsdl"),Response.Output); %>

<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> 

  

对于contractRef 还有soap address这两个节的更改,需要改成上面的方式,实际上是在页面里面重新编码了soap的查询url,这样做的目的也是为了moss托管的web service可以正确定位。具体里面详细的机制我还不是摸得很清楚,因为本身对soap协议没有什么深刻的学习,希望还有达人指教。

  

 

  

如果你的BDC实体描述文件里面WebServiceProxyNamespace是写的自己虚机的地址,也就是说你调用的web service方法是部署在自己的虚机上面的,那么你就可以不需要上面的步骤就可以正常导入运行。但是这样做有一个非常麻烦的地方,运行的时候必须开虚机,要不然web Service是无法调用到的。对于数据库的权限问题,必须在数据库里面添加相应用户的权限,我用的是sql2005,这里应该在sql里面添加我当前域的可以访问moss用户的,对数据库读取的权限。具体的大家参看sql2005的配置,如何添加相应角色。对于部署在虚机上面的web service,也需要在数据库里面添加用户,NT AUTHORITY/NETWORK SERVICE,这样moss才能调用web service方法来访问数据库。Moss的权限这块做的很复杂,结合了ad,rmi这些东西偶都涉猎不深,还有待学习。

  

以上只是自己一些凌乱的心得和经历,很多东西都没有理解的很透彻,就像一个刚入门的孩子,站在wss的门口,看着这座大楼复杂的构架,众多新鲜的事务。很多东西都还需要学习。在这里希望和大家一起交流,一同进步。

北飘一族

  北漂一族,目前负债1W。
  房租交3压1,加上中介黑的费用,一共是1万五左右吧!!!
  本人小本毕业,
  
  房租两室一厅(四环),一个月3300,和别人和摊,
  自己一个月要出1700,
  
  工资目前拿到手的每个月只有2210,
  
  每天盖饭+米粉+面条之类的 20*30=600;
  (早点能省就省了)
  
  水电+网费+煤气
  
  我都不敢想了。
  想买衣服?免了。
  想买点其他的用品?免了。
  想,,,
  
  (唉,肯定有人要砸我,房子租那么贵,不会多找点人?我也想啊,但是房子空间有限啊,人住多了怎么休息啊,本来每天上班就累,还要连睡觉都睡不好?)
  我要求也不高啊,为什么生活就是这样的。唉,温饱问题都解决不了。
  
  ps:想砸的砸吧,我忍。

aspnet页面运行系列分析(1)

  

 

  

iis里面部署的网站,里面对于页面请求的解析以及页面的回发是怎么一个样子的,很多人可能都不是很清楚,其实整个页面处理的过程很有必要了解和理解的,对于一个编程开发者来说,这是非常有必要的。

  

在构建asp.net的运行时环境时,依据设计的原则,充分考虑了可靠性和性能,microsoft采用了被称为一种asp.net garden的模式,这个模型包含二种元素,一种是存在于web服务器进程中的进程内连接器,一个是外部的辅助进程。

  

我们大家部署网站使用的iis,就是一个未托管的可执行程序,它提供了一个基于isapi扩展模块和筛选器模块的可扩展模型,利用这种模型,我们可以直接对特定的资源类型的请求进行管理,说白了就是可以调用自己想对应的程序处理模块来截获处理想对应的资源请求。扩展器和筛选器就是是一些dll

  

Iis本身直接处理的客户端请求的资源类型是十分少的。例如:html页面,文本文件,jpeg,gif图像的传入。对于active server page(*.asp)文件的请求是通过调用名为asp.dllasp专用扩展模块进行解析的。对于asp.net的资源(aspx,asmx,ashx)实际上是采用asp.net isapi的扩展来处理的,该系统组件是aspnet_isapi.dll。它可以处理很多资源类型包括web服务和http处理程序调用。

  

Asp.net isapi扩展没有集成托管的代码,它是用来接受和分派对各种资源的请求的一个控制中心,asp.net isapi负责调用aspnet_wp.exe进程来处理请求,执行的过程是收到asp.net isapi的监控的。

    辅助进程实际上是一小段shell代码,集成了公共语言运行库clr,并且运行托管的代码,它负责处理对aspx,asmx,ashx资源的请求,一般来说,一个给定的计算机只有一个实例,所有当前激活的asp,et应用程序都在里面运行,每个应用程序都是在一个独立的appdomain里面。那么aspnet_isapi怎么和后面的进程进行通信呢?这里他们是采用异步命名管道来进行的,对于辅助进程返回的信息,又是采用同步管道来进行的。这里的通信采用了一个线程池来维护,即aspnet_isapi模块创建了一定数量的命名管道,为不同的通信需求分配线程池里的线程来传送信息。当信息传送完毕以后,就可以断开连接,释放线程池里面占用的线程资源。

aspnet页面运行系列分析(2)

  

前面废话了那么多,终于切入正题了,ASP.NET 请求的处理逻辑可以概括为以下步骤:

  

当请求到达时,IIS 检查资源类型并调用 ASP.NET ISAPI 扩展。如果启用了默认的进程模型,aspnet_isapi会将请求排队,并将请求分配给辅助进程。所有的请求数据都通过异步 I/O 发送。如果启用了 IIS 6 进程模型,请求将自动在辅助进程  (w3wp.exe) 中排队,此辅助进程用于处理应用程序所属的 IIS 应用程序池。IIS 6 辅助进程不了解ASP.NET 和托管代码的任何情况,它只是处理 *.aspx 扩展并加载 aspnet_isapi 模块。当 ASP.NET ISAPI IIS 6 进程模型中运行时,它的工作方式有所不同,仅在 w3wp.exe 辅助进程的上下文中加载 CLR 收到请求后,ASP.NET 辅助进程将通知 ASP.NET ISAPI,它将为请求服务。通知通过同步 I/O 实现。之所以使用同步模型,是因为请求只有在 ISAPI内部请求表中被标记为“executing”,辅助进程才能开始处理它。如果请求已经由特殊的辅助进程进行处理,则不能再将它指定到其他进程,除非原始进程已取消。

  

在辅助进程的上下文中执行请求。有时,辅助进程可能需要回调 ISAPI 以完成请求,也就是需要说枚举服务器变量。这种情况下,辅助进程将使用同步管道,因为这样可以保持请求处理逻辑的顺序完成后,响应被发送到打开了异步管道的aspnet_isapi。现在,请求的状态变为“Done”,之后将从请求表中被删除。如果辅助进程崩溃,正在处理的所有请求仍将保持“executing”状态并持续一段时间。如果 aspnet_isapi 检测到辅助进程已取消,它将自动终止请求并释放所有相关的 IIS 资源。

  

以上说明是指默认的 ASP.NET 进程模型,即在 IIS 5.x 中运行的工作模型。IIS 6Windows Server 2003 提供)的默认工作方式对 ASP.NET 进程模型也有影响。当集成在 IIS 6.0 中时,ASP.NET 1.1 会自动调整自己的工作方式以适应宿主环境。这时,不再需要使用 aspnet_wp 辅助进程,machine.config文件中定义的某些配置参数也被忽略。从 ASP.NET 的角度来看,IIS 6 的最大改变是有关请求的一切都在 aspnet_isapi 的控制之下,且都处在 w3wp.exe 辅助进程的上下文中。辅助进程的帐户是为 Web 应用程序所属的应用程序池设置的帐户。默认情况下,该帐户是NETWORKSERVICE&#151,它是一个内置的弱帐户,在功能上与 ASPNET 等价。辅助进程受一个名为进程回收 (Recycling) 的功能的控制。进程回收具有 aspnet_isapi功能,当现有进程消耗的内存太多、响应太慢或挂起时可以自动启动新进程。出现这种情况时,新请求将由新实例处理,新实例从而变成新的活动进程。但是,指定给旧进程的所有请求仍保持挂起状态。如果旧进程结束了挂起的请求并进入空闲状态,该进程即终止。如果辅助进程崩溃,或者由于其他原因停止处理请求,则所有挂起的请求将被重新指定给新进程。

aspnet页面运行系列分析(3)

   尽管 ASP.NET ISAPI 和辅助进程是 ASP.NET运行时结构的主要组成部分,但还有其他一些可执行文件也发挥着作用。下表列出了所有这些组件。
   aspnet_isapi.dll Win32 DLL(ISAPI 扩展) LOCAL SYSTEM
   aspnet_wp.exe Win32 EXE ASPNET
   aspnet_filter.dll Win32 DLL(ISAPI 筛选器) LOCAL SYSTEM
   aspnet_state.exe Win32 NT Service ASPNET
  aspnet_filter.dll 组件是一个小的 Win32 ISAPI 筛选器,用来备份 ASP.NET 应用程序的无 Cookie会话状态。在 Windows Server 2003 中,当启用 IIS 6 进程模型时,aspnet_filter.dll 还将筛选出 Bin目录中对非可执行资源的请求。
  aspnet_state.exe 的作用对 Web 应用程序更为重要,因为它用于管理会话状态。该项服务是可选的,可以用来在 Web应用程序内存空间之外保存会话状态数据。该可执行文件是一种 NT 服务,既可以在本地运行,也可以远程运行。当该服务被激活后,可以将 ASP.NET应用程序配置为将所有会话信息保存在此进程的内存中。一种类似的方案是提供更为可靠的数据存储方式,不受进程回收和 ASP.NET应用程序故障的影响。该服务在 ASPNET 本地帐户下运行,但可以使用服务控制管理器 (Service Control Manager)接口来配置它。
   另一个应该介绍的可执行文件是 aspnet_regiis.exe,尽管严格来讲,它并不属于 ASP.NET运行时结构。该实用程序可以用来配置环境,以在一台计算机上并行执行不同版本的 ASP.NET,还可用于维修 IIS 和 ASP.NET损坏的配置。该实用程序的工作方式是更新存储在 IIS 配置数据库的根目录和子目录中的脚本映射。脚本映射是资源类型和 ASP.NET模块之间的一种关联关系。最后,还可以使用该工具来显示已安装的 ASP.NET 版本的状态,执行其他配置操作,如授予对特定文件夹的 NTFS权限、创建客户脚本目录。
  

【转】WebGarden模型

   Web Garden 模型可以通过 machine.config 文件中的 <processModel>
  部分进行配置。请注意,<processModel> 部分是唯一不能放在应用程序特定的 web.config 文件中的配置部分。这就是说,Web Garden 模式可以应用到计算机中运行的所有应用程序。但通过使用 machine.config 源文件中的 <location>节点,可以针对各个应用程序调节计算机的设置。
  <processModel> 部分有两个属性可以影响 Web Garden 模型,它们是 webGarden 和cpuMask。webGarden 属性接受布尔值,表示是否使用了多个辅助进程(一个相关的 CPU 对应一个进程)。默认情况下,该属性的值为false。cpuMask 属性保存一个 DWORD 值,该值的二进制表示为能够运行 ASP.NET 辅助进程的 CPU 提供了位屏蔽。其默认值为-1 (0xFFFFFF),表示可以使用所有可用的 CPU。如果 webGarden 属性为 false,则 cpuMask属性的内容将被忽略。cpuMask 属性还为正在运行的aspnet_wp.exe 的副本数设置了上限。
   常言道“闪光的不都是金子”,用在这里很合适。Web Garden模式使得多个辅助进程可以同时运行。但是,需要注意的是所有进程都会有自己的应用程序状态、进程内会话状态、ASP.NET缓存、静态数据以及运行应用程序所需的其他内容。启用 Web Garden 模式之后,ASP.NET ISAPI 将根据 CPU的数量尽可能多地启动辅助进程,每个辅助进程都是下一进程的完整克隆(每一进程都与相应的 CPU密切相关)。为平衡工作负荷,传入的请求以单循环的方式在运行的进程之间进行划分。辅助进程就象在单处理器中一样被回收。请注意,ASP.NET继承了操作系统中所有的 CPU 使用限制,并且不包括实现限制的自定义语义。
   总之,Web Garden模型并不适用于所有应用程序。应用程序的状态越多,其的性能损失也越多。工作数据存储在共享内存的块中,以便一个进程输入的变化可以立即被其他进程得知。但是,处理请求时,工作数据被复制到进程的上下文中。因此,各个辅助进程将处理自己的工作数据,而应用程序的状态越多,性能损失就越大。鉴于此,仔细、明智的应用程序基准测试是绝对必要的。只有重启 IIS 后,对配置文件中 <processModel> 部分所做的更改才会生效。在 IIS 6 中,Web Garden模式的参数保存在 IIS 配置数据库中,webGarden 和 cpuMask 属性被忽略。
  

【转】HTTP管道

  
   ASP.NET ISAPI 扩展启动辅助进程后,它将传递部分命令行参数。辅助进程使用这些参数来执行加载 CLR前需要执行的任务。传递的值包括:COM 和 DCOM 安全性所要求的身份验证等级、可以使用的命名管道的数量和 IIS 进程标识。命名管道的名称是使用IIS 进程标识和允许的管道数随机生成的。辅助进程不接收可用管道的名称,但可以接收识别管道名称所需的信息。
   COM 和 DCOM 安全性与 Microsoft? .NET Framework 有何关系?实际上,CLR 是作为 COM对象提供的。更准确地说,CLR 本身不是由 COM 代码构成的,但是指向 CLR 的接口却是一个 COM 对象。因此,辅助进程加载 CLR的方式与加载 COM 对象的方式相同。
   当 ASPX 请求遇到 IIS 时,Web 服务器将根据选择的身份验证模型(匿名、Windows、Basic 或Digest)来分配一个令牌。当辅助进程收到要处理的请求时,令牌被传递到辅助进程。请求由辅助进程中的线程获取。该线程从最初获取传入请求的 IIS 线程继承身份令牌。在 aspnet_wp.exe 中,负责处理请求的实际帐户取决于在特殊的 ASP.NET应用程序中是如何配置模拟的。如果模拟被禁用(默认设置),则线程将在辅助进程的帐户下运行。默认情况下,该帐户在 ASP.NET 进程模型中为 ASPNET,在 IIS 6 进程模型中为 NETWORKSERVICE。这两个帐户都是“弱”帐户,提供的功能比较有限,可以有效抵挡回复性攻击(Revert-to-self Attack)。(回复性攻击是指将模拟的客户端的安全性令牌回复到父进程令牌。为辅助进程分配弱帐户可以挫败此类攻击。)
   高度概括起来,ASP.NET 辅助进程完成的一项主要任务就是将请求交给一系列称为的 HTTP 管道的托管对象。要激活 HTTP管道,可以创建一个 HttpRuntime 类的新实例,然后调用其 ProcessRequest 方法。如前所述,ASP.NET中始终只运行一个辅助进程(除非启用了 Web Garden 模型),该进程在独立的 AppDomain 中管理所有的 Web 应用程序。每个AppDomain 都有自己的 HttpRuntime 类实例,即管道中的输入点。HttpRuntim对象初始化一系列有助于实现请求的内部对象。Helper 对象包括缓存管理器(Cache对象)和内部文件系统监视器(用于检测构成应用程序的源文件的更改)。HttpRuntime 为请求创建上下文,并用与请求相关的 HTTP信息填充上下文。上下文用 HttpContext 类的实例来表示。另一个在 HTTP 运行时的设置初期创建的 Helper 对象是文本书写器,用于包含浏览器的响应文本。文本书写器是 HttpWriter类的实例,此对象对页面代码以编程方式发送的文本进行缓存。HTTP 运行时被初始化后,它将查找实现请求的应用程序对象。应用程序对象是HttpApplication 类的实例,该类就是 global.asax 文件背后的类。global.asax在编程时是可选的,但在构建结构时是必需的。因此,如果应用程序中没有构建类,则必须使用默认对象。
  

小议委托事件和WPF事件注册

这几天搞微软的WPF培训,其中用到了一个事件的注册,有个同事追根问底,所以只好从委托开始和她说起,自己也再一次对委托事件进行了一个整体的复习,现在写点自己的心得,有不对的地方还请大家指出,本人学的不深刻,所以描述可能有些浅陋,希望大家不要笑话。

对于.net里面的事件,实际上是一种特殊的委托,因为在net里面没有了指针,所以也就不存在了函数指针,那么对于事件驱动的windows程序应该怎么来处理的呢?于是c#里面冒出了一个委托,实际上十分类似于一个函数指针,当你调用委托的时候,实际上是在调用你的委托的订阅的方法。对于一个事件来说,必须得有一个事件发送者,事件的处理,事件触发中所需要的消息。大家看下面的一段代码;

Public Delegate void RoutedEventHandler(object sender,RoutedEventArgs e);

Public event RoutedEventHandler loginPassed;

前面这里定义了一个委托,这个委托的名字为RoutedEventHandler,后面的参数定义了这个事件处理函数必须要像的样子,其实也所就是常见的事件处理函数的样子,因为这里本身就是一个事件委托的定义。下面的一句定义了一个事件,事件的类型是RoutedEventHandler的,事件的名字叫做loginPassed;因为这个事件是公有的类型的,所以只要是本类的对象都可以引用。定义好了委托,以及事件,那么怎么让事件跑起来呢?很简单,你只要让事件订阅相应的方法就可以了。你的方法一定要和委托定义的样子长的差不多,所以一般是

Public void XXXfunction(object sender,RoutedEventArgs){}

然后在你类的构造函数,或者是界面的初始函数里面用事件订阅它就可以了,例如我们刚才定义的事件对象loginPassed+=new RoutedEventHandler(XXXfunction);

  

那么事件是什么时候触发的呢?当然是你想要触发的时候出发拉,调用logingPassed(yourobject,yourargs);就可以完成你的事件触发了,前面第一个是你触发当前事件的发送者,后面是你触发事件所要发送的信息。

怎么样,比较简单吧。下面来个稍微复杂一点的,在WPF里面注册你自己的事件,实际上也就是在FCL里面注册你自己定义的事件。

当你在WPF里面定义的自定义控件,要想公布你的控件的事件以及属性出来,做法和原来asp.net的差不多,但是多了一个注册的过程,因为你的事件要让blend能识别,以便在时间轴可以调用触发,所以必须注册到WPF的事件列表里面(实际上是注册到FCL的事件列表里面了)。我们来看下面的代码;

 

Public static readonly RoutedEvent LoginPassedEvent =

  EventManager.RegisterRoutedEvent(“LoginPassed”,

RoutingStrategy.Bubble,  

typeof(RoutedEventHandler),  

typeof(UserLoginControl));

这里是注册一个名叫loginPassed的事件到RoutedEvent列表里面去了,类型为RoutedEventHandler,并且返回了一个句柄,为RoutedEvent类型,实际上它就是一个描述列表里面的事件类型的类。

下面这句:

Public event RoutedEventHandler LoginPassed

{

  Add{Addhandler(LoginPassedEvent,value);}

  Remove{RemoveHandler(LoginPassedEvent,value);}

}

这里以访问器的方式注册了一个LoginPassed的事件,里面包含了addRemove方法,分别是将刚才注册了的返回的事件句柄加入到消息handler里面和从消息handler里面移出。再看下面这个函数,对于这种注册上去的事件,消息处理函数的事件通过RaiseEvent();转发才能被WPF截获,也就是说通过ui的事件发送函数发送,这样就能保证事件能够被截获处理。

所以有了下面的函数来发送事件:

Void RaiseLoginPassedEvent()

{

         RoutedEventArgs newEventArgs=new RoutedEventArgs(发出事件的类写这里);
         RaisedEvent(newEventArgs);

}

  

然后在你要触发的地方直接调用RaiseLoginPassedEvent()这个函数就可以了,不过要记得订阅事件处理的方法哦,要不然事件就不知道调用什么方法进行处理了。

项目级审批-部署(续)

对于SharePoint这一块的内容,自己也捣鼓了快一个月了。调通了一个老大布置下来的项目,也从找BUG中理解了不少的东西。其实对于整个SharePoint体系,自己目前了解的还是比较浮浅,而且了解的东西还比只是很少的一部分,目前所能说的,也只是自己在学习中间的一些心得和经验,拿出来和大家一起分享,希望能帮助到一些人少走一些弯路,水平有限大家不要打击偶哦,如果有错误希望大家指出,一同学习进步。
  

Moss2007 使用 Microsoft Windows SharePoint Services 3.0为个人、信息和公司创建门户页面。这些页面可以通过公司和管理工具来扩展 Windows SharePoint Services站点的功能,并且使得团队能够在他们的站点中向整个企业发布信息。对于自己机器上装载的moss2007其实是对wss3.0的扩展和扩充服务。
  

整个MOSS其实结构并不复杂,对于大体的框架来说,整个程序是以一个应用服务程序的形式提供的,大家在搭建moss网站的时候肯定会注意到,首先是创建一个web应用服务程序,然后是创建一个网站集,之后是创建一个web,再之后是在网站里面创建自己所需要的元素。其实在编程过程中,很多时候我们用的SPSite类就是这里的网站集,而SPWeb就是当前的site,一个网站集里面可以有多个网站,一个应用服务提供程序可以为多个网站集提供服务。对于以前20版本的处理机制这里就不再说了.这里的就浮浅的提一下30的工作原理。其实很多时候,对于asp.net的页面解析机制,想必做过web程序的人都不会陌生。
  

下面是一个网络上面经常可以看到的一个图片,当然是包含在moos2007sdk里面的,仔细的学习者可能在sdk里面看到过。当http请求来到时,服务器是通过iis来截获信息进行处理的,调用的是isap来对页面进行解析,实际上调用的动态连接库是asp.dll。但是对于处理的请求,wss有自己的一套截获处理程序。进程文件名是w3wp.exe。当页面请求被识别为wss的页面时,wss调用自己的模块对请求进行处理。提到页面的解析,这里就必须说一下wss的页面解析机制,在kaneboy大哥blog上面有写过一篇文章来解释。主要的内容就是说,在wss里面,页面有两种类型,一种是application page另外一种是site pageApplication page是指在sharepoint用到的固态页面,一般路径都是在_layouts/目录下,物理上是在Program FilesCommon FilesMicrosoft SharedWeb Server Extensions12TEMPLATELayouts里面。这种页面不能被用户定制,也就是说不能加载到定制的context里面,而site pagesharepoint里面的普通页面,这些页面都是位于文档库,或者站点首页的,这类页面最大的特点是可以被用户定制,其真实数据实际上是储存在wss的数据库里面。对于一般的application页面,wss是以asp的页面执行的,而对于site页面,处理就变得复杂的多,实际上我们创建自己定制的网站,在iis目录里面你也许可以发现一些痕迹,但是打开来一看什么都没有,其实里面存在的只是一个模板而已,实际的网页数据是存在数据库里面的,当用户请求页面的时候,sharepoint从数据库里面调用出响应的数据对页面进行构建,解析,编译成为一个dll的文件,然后载入,运行,输出。为了保证性能,编译的东西会在内存里面保存,以保证下次快速调用。Sdk里面给的图片很好的说明了这个过程,希望大家仔细的研究下。
  

其实了解wss的这些东西,里面他里面的一些东西就很简单了。这里用我做msdn上面那个项目级部署的例子的过程来说明一些细小的问题。具体的例程大家可以在sharepoint.org.cn里面下载得到。对于整个解决方案,里面包含了三大块内容,有两个是负责显示日志记录的模块,当然使用aspx的页面写的,一个是用来回传xml描述的日志信息的ashx。其中显示日志的页面用到了mossexcel service具体的要解说的话又可以写一篇文章了,以后有空再写,不过网上也有不少解释这些东西,这里我就不废话了。对于整个操作,大致是这样的过程,获得当前网站句柄,获得当前页面句柄,创建当前的日志访问类,读取对应的id的实体记录,写道绑定的单元里面。对于日志实体的访问,这里用了一个很有发光点的东西,SPSecurity.RunWithElevatedPrivileges,这个代理实现了权限的提升,完成了匿名对一些系统授权资源的访问,具体的还是去查msdn  

对于整个项目里面包含的elements是通过itemautiting里面的elements.xml来描述的,而通过解决方案部署的程序,自然少不了manifest.xml描述文件,所有的aspx,ashx页面的描述是在feature.xml里面描述的,对于部署的激活操作,程序继承了SPFeatureReceiver类,并且重载了FeatureActivated, FeatureDeactivating这两个函数,用于激活自己的解决方案。在程序编译的时候,会自动把当前项目部署到你的moss里面,具体的其实是调用了nstall这个批处理文件,部署的就不说了。

如果你的moss2007是中文的,那么恭喜你,你会发现你的项目部署上去以后无法激活,其实本来就是一个很简单的问题,看下列语句。
  

if (!ListExists(“AuditLogs”, site)) {

        //SPListTemplate template = site.ListTemplates[“Document Library”];

        Guid docLibID = site.Lists.Add(“AuditLogs”, “Library for Audit Log Workbooks”, SPListTemplateType.DocumentLibrary);

        SPList docLib = site.Lists[docLibID];  

        docLib.OnQuickLaunch = true;

        docLib.Update();  

      }

这里就是判断文档库列表里面里面是否存在auditlogs这个文档库,如果不存在的话就构建一个模板创建它,并且加到当前列表里面,如果存在那就不同再创建了。因为你会发现每次点了激活以后,你的网站标题都会添加一个(auditing)那么前面的代码是正确执行了的,所以程序错误就定位到了这里。其实怎么看这段代码都没有问题,其实他也真的没有什么问题(当然是在英文版本里面),实际上在执行add方法的时候是失败的,因为你前面创建的模板,是不存在的,为什么呢,因为对于moss来说,解析中文模板名字是变成了英文加数字,那么在中文版里也是如此,但是中文版里面的Document Library无法索引到,所以改成文档库以后就搞定了,可以正常激活了,当然,还有一种比较淫荡的办法是,手工在网站里面添加一个叫auditing的文档库,同样也就绕过这段代码的执行,激活成功。