C# 如何在Http模块中获取引发的事件

C# 如何在Http模块中获取引发的事件,c#,asp.net,httpmodule,C#,Asp.net,Httpmodule,我想获取哪个类中的哪个事件导致Http模块中的服务器发出请求 例如,当用户单击Page1中的按钮时,我想得到:Button1\u在Page1类中单击,或者当用户更改该页面中的下拉列表选定索引时,我想得到DropdownList1\u SelectedIndex在Page1类中更改 谢谢页面事件与页面关联。模块是生命周期事件。您不会看到事件模块中的任何单击类型事件,也不会像其他帖子中的这些一样进行侦听 BeginRequest AuthenticateRequest AuthorizeReques

我想获取哪个类中的哪个事件导致Http模块中的服务器发出请求

例如,当用户单击Page1中的按钮时,我想得到:Button1\u在Page1类中单击,或者当用户更改该页面中的下拉列表选定索引时,我想得到DropdownList1\u SelectedIndex在Page1类中更改


谢谢

页面事件与页面关联。模块是生命周期事件。您不会看到事件模块中的任何单击类型事件,也不会像其他帖子中的这些一样进行侦听

BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequestCache
AcquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
UpdateRequestCache
EndRequest

页面事件与页面关联。模块是生命周期事件。您不会看到事件模块中的任何单击类型事件,也不会像其他帖子中的这些一样进行侦听

BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequestCache
AcquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
UpdateRequestCache
EndRequest

您的问题非常广泛,以下MSDN库文档参考可能有助于您理解此过程:

以下是ASP.NET 4.0的事件和请求管道:

验证请求,该请求检查浏览器发送的信息,并确定其是否包含潜在的恶意标记。 如果在Web.config文件的UrlMappingsSection部分中配置了任何URL,则执行URL映射。 引发BeginRequest事件。 引发AuthenticateRequest事件。 引发PostAuthenticateRequest事件。 引发AuthorizeRequest事件。 引发PostAuthorizerRequest事件。 引发ResolveRequestCache事件。 引发PostResolveRequestCache事件。 [IIS 5.0/6.0]根据应用程序配置文件中映射的请求资源的文件扩展名,选择一个实现IHttpHandler的类来处理请求。如果请求是从page类派生的对象页,并且需要编译该页,则ASP.NET会在创建该页的实例之前编译该页。[IIS 7.0]引发MapRequestHandler事件。根据请求的资源的文件扩展名选择适当的处理程序。处理程序可以是本机代码模块(如IIS 7.0 StaticFileModule)或托管代码模块(如处理.aspx文件的PageHandlerFactory类)。 引发PostapRequestHandler事件。 引发AcquisiteRequestState事件。 引发PostAcquireRequestState事件。 引发PreRequestHandlerExecute事件。 调用ProcessRequest方法或请求的相应IHttpHandler类的异步版本IHTTPassynchandler.BeginProcessRequest。例如,如果请求是针对某个页面的,则当前页面实例将处理该请求。 引发PostRequestHandlerExecute事件。 引发ReleaseRequestState事件。 引发PostReleaseRequestState事件。 如果定义了筛选器属性,则执行响应筛选。 引发UpdateRequestCache事件。 引发PostUpdateRequestCache事件。 [IIS 7.0]引发LogRequest事件。 [IIS 7.0]引发PostLogRequest事件。 引发EndRequest事件。 引发PreSendRequestHeaders事件。 引发PreSendRequestContent事件。 注意:仅当应用程序在IIS 7.0和.NET Framework 3.0或更高版本中以集成模式运行时,才支持MapRequestHandler、LogRequest和PostLogRequest事件


以下参考资料:

您的问题非常广泛,以下MSDN库文档参考资料可能有助于您理解此过程:

以下是ASP.NET 4.0的事件和请求管道:

验证请求,该请求检查浏览器发送的信息,并确定其是否包含潜在的恶意标记。 如果在Web.config文件的UrlMappingsSection部分中配置了任何URL,则执行URL映射。 引发BeginRequest事件。 引发AuthenticateRequest事件。 引发PostAuthenticateRequest事件。 引发AuthorizeRequest事件。 引发PostAuthorizerRequest事件。 引发ResolveRequestCache事件。 引发PostResolveRequestCache事件。 [IIS 5.0/6.0]根据应用程序配置文件中映射的请求资源的文件扩展名,选择一个实现IHttpHandler的类来处理请求。如果请求是从page类派生的对象页,并且需要编译该页,则ASP.NET会在创建该页的实例之前编译该页。[IIS 7.0]引发MapRequestHandler事件。根据请求的资源的文件扩展名选择适当的处理程序。处理程序可以是本机代码模块(如IIS 7.0 StaticFileModule)或托管代码模块(如处理.aspx文件的PageHandlerFactory类)。 引发PostapRequestHandler事件。 引发AcquisiteRequestState事件。 引发PostAcquireRequestState事件。 引发PreRequestHandlerExecute事件。 调用ProcessRequest方法或请求的相应IHttpHandler类的异步版本IHTTPassynchandler.BeginProcessRequest。例如,如果请求是一个页面,则当前页面i nstance处理请求。 引发PostRequestHandlerExecute事件。 引发ReleaseRequestState事件。 引发PostReleaseRequestState事件。 如果定义了筛选器属性,则执行响应筛选。 引发UpdateRequestCache事件。 引发PostUpdateRequestCache事件。 [IIS 7.0]引发LogRequest事件。 [IIS 7.0]引发PostLogRequest事件。 引发EndRequest事件。 引发PreSendRequestHeaders事件。 引发PreSendRequestContent事件。 注意:仅当应用程序在IIS 7.0和.NET Framework 3.0或更高版本中以集成模式运行时,才支持MapRequestHandler、LogRequest和PostLogRequest事件


要遵循的引用:

您要查找的事件特定于asp.net页面模型。Http模块基于较低级别的传输,不会用于捕获页面事件


您能提供更多详细信息吗?

您要查找的事件特定于asp.net页面模型。Http模块基于较低级别的传输,不会用于捕获页面事件


您能提供更多详细信息吗?

我建议,如果您从一个网站开始,从页面继承一个类,并使您的所有页面从该类继承

public abstract class LoggingPage : System.Web.UI.Page
{
    protected override void RaisePostBackEvent(
        IPostBackEventHandler sourceControl, string eventArgument)
    {
        //doing something with the information.
        EventLog.WriteEntry("Page event for " + sourceControl.UniqueID + " at " + this.Request.Url);

        //then call the base implementation
        base.RaisePostBackEvent(sourceControl, eventArgument);
    }
}
如果由于异常而需要获取事件的信息,而您永远无法获取RaisePostBackEvent,那么您需要在模块中处理HttpApplication的PreRequestHandlerExecute,并在请求中获取2个字段

public class LoggingModule : System.Web.IHttpModule
{
    private HttpApplication _app;

    public void Dispose() 
    {
        this._app.PreRequestHandlerExecute -= new EventHandler(this.PreRequestExecution);
    }

    public void Init(HttpApplication application)
    {
        this._app = application;
        this._app.PreRequestHandlerExecute += new EventHandler(this.PreRequestExecution);
    }

    private void PreRequestExecution(object sender, EventArgs e)
    {
        var request = this._app.Context.Request;
        var target = request.Form["__EVENTTARGET"];
        var arg = request.Form["__EVENTARGUMENT"];
        //this gives you enough information about events
        //you need to check if they are null before using them (target and arg)
        //through the same request you can get extra info including URL
    }
}
更新: 如果您关心的是安全性,并且由于您的系统中实现了角色,我建议您使用system.security.Permissions.PrincipalPermissionAttribute来装饰事件处理程序,如下所示:

protected void Page_Load()
{
    myButton.Click += new EventHandler(this.myButton_Click);
}

[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]
private void myButton_Click(object sender, EventArgs e)
{
    //your code to handle the event
}
您可以多次添加属性以满足您的需要


希望这能有所帮助。

我建议,如果您从一个网站开始,从页面继承一个类,并使您的所有页面从该类继承

public abstract class LoggingPage : System.Web.UI.Page
{
    protected override void RaisePostBackEvent(
        IPostBackEventHandler sourceControl, string eventArgument)
    {
        //doing something with the information.
        EventLog.WriteEntry("Page event for " + sourceControl.UniqueID + " at " + this.Request.Url);

        //then call the base implementation
        base.RaisePostBackEvent(sourceControl, eventArgument);
    }
}
如果由于异常而需要获取事件的信息,而您永远无法获取RaisePostBackEvent,那么您需要在模块中处理HttpApplication的PreRequestHandlerExecute,并在请求中获取2个字段

public class LoggingModule : System.Web.IHttpModule
{
    private HttpApplication _app;

    public void Dispose() 
    {
        this._app.PreRequestHandlerExecute -= new EventHandler(this.PreRequestExecution);
    }

    public void Init(HttpApplication application)
    {
        this._app = application;
        this._app.PreRequestHandlerExecute += new EventHandler(this.PreRequestExecution);
    }

    private void PreRequestExecution(object sender, EventArgs e)
    {
        var request = this._app.Context.Request;
        var target = request.Form["__EVENTTARGET"];
        var arg = request.Form["__EVENTARGUMENT"];
        //this gives you enough information about events
        //you need to check if they are null before using them (target and arg)
        //through the same request you can get extra info including URL
    }
}
更新: 如果您关心的是安全性,并且由于您的系统中实现了角色,我建议您使用system.security.Permissions.PrincipalPermissionAttribute来装饰事件处理程序,如下所示:

protected void Page_Load()
{
    myButton.Click += new EventHandler(this.myButton_Click);
}

[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]
private void myButton_Click(object sender, EventArgs e)
{
    //your code to handle the event
}
您可以多次添加属性以满足您的需要


希望这能有所帮助。

关于你的问题,我注意到这样一句话:


我想开发一个安全系统,为可以访问此事件并使用会话和此属性检查授权的角色的事件添加一些属性。我想获取事件名称,然后获取属于它的属性并检查授权

由于事件是在类中注册的,而在模块/处理程序阶段不可用,因此无法执行您的请求

但是,总有一些选择,我可以看到您试图实现的目标:-我的解决方案是通过调用方法myEventHooks.HookAllthis来注册所有事件;在钩子实现中,检查安全性,或者在检查失败时抛出异常,或者删除所有已注册的事件——以您认为合适的方式填补空白

请注意,更改子级/树时,还需要更新事件挂钩以绑定到它们的所有方法。进行绑定的最简单方法是重写基页中的RaisePostBackEvent,然后挂接所有内容

该解决方案可以通过两种不同的方式进行改进;最明显的是使处理更通用,并且缺少0参数处理程序。为了获得许可,我尽量简单。这应该让你开始

我的解决方案有两部分:1是通用钩子类,2是表单中的实现。当前解决方案是惰性的,例如,我将事件处理程序放在队列的末尾,而不是队列的前端。您应该能够通过使用GetInvocationList或类似的工具来解决这个问题

泛型钩子类基本上钩住事件,并在调用事件时激发:

public class EventHooks
{
    private class EventHooksEquality : IEqualityComparer<Tuple<string, object>>
    {
        public bool Equals(Tuple<string, object> x, Tuple<string, object> y)
        {
            return x.Item1.Equals(y.Item1) && object.ReferenceEquals(x.Item2, y.Item2);
        }

        public int GetHashCode(Tuple<string, object> obj)
        {
            return obj.Item1.GetHashCode();
        }
    }

    public void CheckSecurity(string eventName, object container) 
    {
        // Add your security code that checks attributes and the likes here
    }

    private abstract class BaseHookHandler
    {
        protected BaseHookHandler(object container, string eventName, EventHooks hooks)
        {
            this.hooks = hooks;
            this.container = container;
            this.eventName = eventName;
        }

        protected string eventName;
        protected object container;
        protected EventHooks hooks;
    }

    private class HookHandler<T1> : BaseHookHandler
    {
        public HookHandler(object container, string eventName, EventHooks hooks)
            : base(container, eventName, hooks)
        {
        }
        public void Handle(T1 t1)
        {
            hooks.CheckSecurity(eventName, container);
        }
    }

    private class HookHandler<T1, T2> : BaseHookHandler
    {
        public HookHandler(object container, string eventName, EventHooks hooks)
            : base(container, eventName, hooks)
        {
        }
        public void Handle(T1 t1, T2 t2)
        {
            hooks.CheckSecurity(eventName, container);
        }
    }
    // add more handlers here...

    public void HookAll(object obj)
    {
        foreach (var eventHandler in obj.GetType().GetEvents()) 
        {
            Hook(obj, eventHandler.Name);
        }
    }

    public void Hook(object obj, string eventHandler)
    {
        if (obj == null)
        {
            throw new Exception("You have to initialize the object before hooking events.");
        }

        // Create a handler with the right signature
        var field = obj.GetType().GetEvent(eventHandler);
        var delegateInvoke = field.EventHandlerType.GetMethod("Invoke");
        Type[] parameterTypes = delegateInvoke.GetParameters().Select((a) => (a.ParameterType)).ToArray();

        // Select the handler with the correct number of parameters
        var genericHandler = Type.GetType(GetType().FullName + "+HookHandler`" + parameterTypes.Length);
        var handlerType = genericHandler.MakeGenericType(parameterTypes);
        var handlerObject = Activator.CreateInstance(handlerType, obj, eventHandler, this);
        var handler = handlerType.GetMethod("Handle");

        // Create a delegate
        var del = Delegate.CreateDelegate(field.EventHandlerType, handlerObject, handler);

        // Add the handler to the event itself
        field.AddEventHandler(obj, del);
    }
}
基类中的使用可按以下示例进行:

    protected override void RaisePostBackEvent(
        IPostBackEventHandler sourceControl, string eventArgument)
    {
        // Hook everything in Page.Controls
        Stack<Control> st = new Stack<Control>();
        st.Push(Page);

        while (st.Count > 0)
        {
            var control = st.Pop();
            eventHooks.HookAll(control);
            foreach (Control child in control.Controls)
            {
                st.Push(child);
            }
        }

        // Raise events
        base.RaisePostBackEvent(sourceControl, eventArgument);
    }

    private EventHooks hooks = new EventHooks();

关于你的问题,我注意到这样一句话:


我想开发一个安全系统,为可以访问此事件并使用会话和此属性检查授权的角色的事件添加一些属性。我想获取事件名称,然后获取属于它的属性并检查授权

由于事件是在类中注册的,而在模块/处理程序阶段不可用,因此无法执行您的请求

但是,总有一些选择,我可以看到您试图实现的目标:-我的解决方案是通过调用方法myEventHooks.HookAllthis来注册所有事件;在钩子实现中,检查安全性并抛出异常 n或在检查失败时删除所有已注册事件-按您认为合适的方式填补空白

请注意,更改子级/树时,还需要更新事件挂钩以绑定到它们的所有方法。进行绑定的最简单方法是重写基页中的RaisePostBackEvent,然后挂接所有内容

该解决方案可以通过两种不同的方式进行改进;最明显的是使处理更通用,并且缺少0参数处理程序。为了获得许可,我尽量简单。这应该让你开始

我的解决方案有两部分:1是通用钩子类,2是表单中的实现。当前解决方案是惰性的,例如,我将事件处理程序放在队列的末尾,而不是队列的前端。您应该能够通过使用GetInvocationList或类似的工具来解决这个问题

泛型钩子类基本上钩住事件,并在调用事件时激发:

public class EventHooks
{
    private class EventHooksEquality : IEqualityComparer<Tuple<string, object>>
    {
        public bool Equals(Tuple<string, object> x, Tuple<string, object> y)
        {
            return x.Item1.Equals(y.Item1) && object.ReferenceEquals(x.Item2, y.Item2);
        }

        public int GetHashCode(Tuple<string, object> obj)
        {
            return obj.Item1.GetHashCode();
        }
    }

    public void CheckSecurity(string eventName, object container) 
    {
        // Add your security code that checks attributes and the likes here
    }

    private abstract class BaseHookHandler
    {
        protected BaseHookHandler(object container, string eventName, EventHooks hooks)
        {
            this.hooks = hooks;
            this.container = container;
            this.eventName = eventName;
        }

        protected string eventName;
        protected object container;
        protected EventHooks hooks;
    }

    private class HookHandler<T1> : BaseHookHandler
    {
        public HookHandler(object container, string eventName, EventHooks hooks)
            : base(container, eventName, hooks)
        {
        }
        public void Handle(T1 t1)
        {
            hooks.CheckSecurity(eventName, container);
        }
    }

    private class HookHandler<T1, T2> : BaseHookHandler
    {
        public HookHandler(object container, string eventName, EventHooks hooks)
            : base(container, eventName, hooks)
        {
        }
        public void Handle(T1 t1, T2 t2)
        {
            hooks.CheckSecurity(eventName, container);
        }
    }
    // add more handlers here...

    public void HookAll(object obj)
    {
        foreach (var eventHandler in obj.GetType().GetEvents()) 
        {
            Hook(obj, eventHandler.Name);
        }
    }

    public void Hook(object obj, string eventHandler)
    {
        if (obj == null)
        {
            throw new Exception("You have to initialize the object before hooking events.");
        }

        // Create a handler with the right signature
        var field = obj.GetType().GetEvent(eventHandler);
        var delegateInvoke = field.EventHandlerType.GetMethod("Invoke");
        Type[] parameterTypes = delegateInvoke.GetParameters().Select((a) => (a.ParameterType)).ToArray();

        // Select the handler with the correct number of parameters
        var genericHandler = Type.GetType(GetType().FullName + "+HookHandler`" + parameterTypes.Length);
        var handlerType = genericHandler.MakeGenericType(parameterTypes);
        var handlerObject = Activator.CreateInstance(handlerType, obj, eventHandler, this);
        var handler = handlerType.GetMethod("Handle");

        // Create a delegate
        var del = Delegate.CreateDelegate(field.EventHandlerType, handlerObject, handler);

        // Add the handler to the event itself
        field.AddEventHandler(obj, del);
    }
}
基类中的使用可按以下示例进行:

    protected override void RaisePostBackEvent(
        IPostBackEventHandler sourceControl, string eventArgument)
    {
        // Hook everything in Page.Controls
        Stack<Control> st = new Stack<Control>();
        st.Push(Page);

        while (st.Count > 0)
        {
            var control = st.Pop();
            eventHooks.HookAll(control);
            foreach (Control child in control.Controls)
            {
                st.Push(child);
            }
        }

        // Raise events
        base.RaisePostBackEvent(sourceControl, eventArgument);
    }

    private EventHooks hooks = new EventHooks();


我想开发一个安全系统,为可以访问此事件的角色的事件添加一些属性,并使用会话和此属性检查授权。我想获取事件名称,然后获取属于它的属性,并检查授权两个不同的事件模型,一个用于页面asp.net控件,另一个用于web传输请求/答复。我不认为使用http模块可以做到这一点。我想开发一个安全系统,为可以访问此事件的角色的事件添加一些属性,并使用会话和此属性检查授权。我想获取事件名称,然后获取属于它的属性,并检查授权两个不同的事件模型页面asp.net控件,其中一个用于传输web请求/响应。我不认为使用http模块可以实现这一点。为什么您需要了解模块级别的事件?这是否回答了您的问题?为什么您需要了解模块级别的事件?这是否回答了您的问题?谢谢亲爱的朋友,但您能扩展第二个代码部分吗。受保护的覆盖无效的RaisePostBackEvent。。。?我使用此代码来创建该方法,但它不执行:hooks.HookAllPage.Controls;请在开始之前帮助我,实现为堆栈。谢谢亲爱的@Stefan de Bruijn。我在一个空白页面中放置了一个按钮,并在Click event中编写了一些代码。对不起,我不知道如何使用您的代码。我如何使用事件名称进行授权?如何使用变量挂钩?在CheckSecurity方法中放置System.Diagnostics.Debug.WriteLinefoo,并在其上放置断点。点击按钮。请注意,在提供您请求的信息时如何调用CheckSecurity,例如,在哪个对象上触发了哪个事件。从那以后,你可以继续进行安全检查并采取适当的行动。就我个人而言,我会使用属性来做这件事,但我想从你目前的评论来看,这有点超出你的理解范围;一个简单的交换机/案例或数据库调用或类似的东西就足够了。谢谢。我得到了。有一个PROMLE。只需点击一下按钮,检查安全就触发了大约25次。只需单击一下,它就会导致大约25个连接…谢谢亲爱的朋友,但您能否扩展第二个代码部分。受保护的覆盖void RaisePostBackEvent。。。?我使用此代码来创建该方法,但它不执行:hooks.HookAllPage.Controls;请在开始之前帮助我,实现为堆栈。谢谢亲爱的@Stefan de Bruijn。我在一个空白页面中放置了一个按钮,并在Click event中编写了一些代码。对不起,我不知道如何使用您的代码。我如何使用事件名称进行授权?如何使用变量挂钩?在CheckSecurity方法中放置System.Diagnostics.Debug.WriteLinefoo,并在其上放置断点。点击按钮。请注意,在提供您请求的信息时如何调用CheckSecurity,例如,在哪个对象上触发了哪个事件。从那以后,你可以继续进行安全检查并采取适当的行动。就我个人而言,我会使用属性来做这件事,但我想从你目前的评论来看,这有点超出你的理解范围;一个简单的交换机/案例或数据库调用或类似的东西就足够了。谢谢。我得到了。有一个PROMLILE。只需点击一下按钮,CealStand大约有25个时间。考虑一下我想从数据库中获取数据进行自动处理,只需点击一次就可以产生大约25的连接。