用户单击 ASP.NET Web 表单上的按钮与计时器运行调用相同按钮单击事件的方法之间的区别?

Posted

技术标签:

【中文标题】用户单击 ASP.NET Web 表单上的按钮与计时器运行调用相同按钮单击事件的方法之间的区别?【英文标题】:Difference between when a user clicks button on an ASP.NET web form, and when a timer runs a method that calls the same button click event? 【发布时间】:2019-08-30 15:42:16 【问题描述】:

我创建了一个带有按钮的 ASP.NET Web 表单(页面?)在一张桌子上。单击事件按钮中的代码也应该刷新网页以显示更新的数据。当用户物理单击按钮时,这在大多数情况下都有效。但是,当我创建一个计时器对象来运行一个调用单击事件的方法时,我收到一个错误:System.NullReferenceException:'对象引用未设置为对象的实例。 System.Web.HttpContext.Current.get 返回 null。什么给了?

就像我说的,当有物理用户单击按钮时它可以工作,但最终我想自动打开 Access db 的任务,以及用新数据刷新 Web 表单(页面?)。

这是按钮点击代码。注释行是我已经尝试过的:

    protected void btnRefresh_Click(object sender, EventArgs e)
    
        Process.Start(@"C:\Users\mperea\Desktop\DC8SortMonitor.accdb");           

        HttpContext.Current.Response.Redirect("~/Default.aspx");

        //Response.Redirect("~/Default.aspx");
        //Page.Response.Redirect(Page.Request.Url.ToString(), true);
        //Server.TransferRequest(Request.Url.AbsolutePath, false);

        //Trying open access with this didn't work:
        //Access.Application oAccess = new Access.ApplicationClass();//oAccess.OpenCurrentDatabase(@"C:\Users\mperea\Desktop\DC8SortMonitor.accdb");
     

这是一个计时器对象,旨在以编程方式执行调用点击事件的方法:

    protected void Page_Load(object sender, EventArgs e)
    

        Timer aTimer;

        //Create a timer and set a two second interval.
        aTimer = new System.Timers.Timer();
        aTimer.Interval = 15000;

        //ElapsedEventHandler btnRefresh_Click = null;
        //Hook up the Elapsed event for the timer. 
        aTimer.Elapsed += timer;

        //Have the timer fire repeated events(true is the default)
        aTimer.AutoReset = true;

        //Start the timer
        aTimer.Enabled = true;
     

以及定时器调用的方法:

    public void timer(object sender, EventArgs e)
    
        btnRefresh_Click(null, null);
    

【问题讨论】:

在你走这条路之前,如果你想在服务器端发生定时事件,你不应该使用前端来创建它们。使用适当的服务端组件(即 Windows 服务),或者如果必须,使用 Hangfire 等工具。 对于常用方法,我一般都是创建一个非事件方法,然后从事件中调用代码 谢谢,大卫!您能否提供有关此特定方法为何不起作用的任何见解?我不一定要让它发生在服务器端。如果它可以在客户端工作,那就这样吧,但是如何? 不管具体错误如何,通过这种方法它永远不会正常工作,因为当 http 请求结束并且响应返回给浏览器时,您的 c# 代码将停止运行。它不会等待计时器运行。这就是 Web 应用程序的工作方式:它们是无状态的,它们在请求进入时启动、执行、返回响应并再次停止,直到下一个请求。这就是为什么如果您想要在常规计时器上长时间运行的作业,您需要后台服务 @ADyson 非常感谢!非常感谢您的 cmets。我对开发还很陌生,每一个小消息都有很大的帮助。 :) 【参考方案1】:

首先让我感到震惊的是 button_click 方法需要 object senderEventArgs e,您将其作为 null 传入,因为显然您没有提供它的信息。

您不应该以这种方式调用您的按钮事件处理程序。相反,您应该将共享代码从您的 click 方法移出到另一个方法中,该方法不需要您可以从任何地方调用的那些参数。

protected void btnRefresh_Click(object sender, EventArgs e)

    Refresh();
 

现在你的刷新方法

public void Refresh()

    Process.Start(@"C:\Users\mperea\Desktop\DC8SortMonitor.accdb");

    Response.Redirect("~/Default.aspx");

    //HttpContext.Current.Response.Redirect("~/Default.aspx");
    //Page.Response.Redirect(Page.Request.Url.ToString(), true);
    //Server.TransferRequest(Request.Url.AbsolutePath, false);

    //Access.Application oAccess = new Access.ApplicationClass();//oAccess.OpenCurrentDatabase(@"C:\Users\mperea\Desktop\DC8SortMonitor.accdb");

还有计时器

 public void timer(object sender, EventArgs e)

    Refresh();

点击事件处理程序应该只真正具体地处理事件,并且与按钮的作用相关的任何功能都应该在单独的方法中。通常一个按钮的工作量很小以至于没有必要,但像这样的情况说明了为什么它通常是一个好主意。

【讨论】:

感谢您的回答。我做了你建议的一切,但仍然得到与原始问题相同的错误。我想这与我调用刷新方法的上下文有关。嗯【参考方案2】:

您不能使用运行服务器端的计时器和代码来单击/运行另一个按钮/代码服务器端并期望控件值可以被使用、读取、抓取或修改。这行不通。

请记住,当您实际单击按钮时,您会开始运行浏览器端代码,而最先发生的事情是将完整的网页回发到服务器。那时(也只有那时),您用 c# 编写的实际事件代码开始运行。

如果您只是调用其他代码位,甚至是按钮事件,则代码可以运行,但无需完整的网页回传即可运行。在您的任何代码可以查看/获取/修改控件的值之前,必须将整个网页传输到服务器。

真正完成这项工作的唯一方法是设置一些运行浏览器端的 javascript 作为计时器,然后当它触发(单击)您想要在网页上单击的实际按钮(而不是服务器端代码)时,那么按钮点击事件将:

将完整的网页回传到服务器(并传输所有控件/文本框等的内容)。

然后在网页传输发生后,给定点击事件的按钮代码现在将运行,当它按照说明运行时,它将使用网页中的数据。

因此,您不能在 c# 中使用将运行服务器端代码的计时器,并期望按钮代码能够正常工作,因为您必须首先在客户端进行整页回传以传输当前控件中的值。

在您的情况下,通过计时器的按钮代码将运行,但网页未发布(发回)到服务器端。因此,您的代码将运行,但不会使用网页中的任何数据。

因此,假设当用户在网页中输入内容时,您的计时器代码可以运行按钮事件,但用户仍在网页上输入内容,并且网页上的数据还没有转移到服务器。因此,在用 c# 编写的按钮事件可以检查页面上的任何值之前,您需要完整的回帖。

如前所述,您可以编写浏览器端 JavaScript,这样的代码能够在完整回发之前查看、使用和查看任何控件。当然,这样的 JavaScript 代码也可以触发/单击该按钮。因此,必须将 Web 浏览器中/来自 Web 浏览器的值传输到服务器端,以便 c# 能够查看或使用该页面上控件中的当前值。

【讨论】:

非常感谢您的详细回复。这对我作为开发人员的发展真的很有价值……哈。看来我还有一些工作要做。这真的很有帮助。

以上是关于用户单击 ASP.NET Web 表单上的按钮与计时器运行调用相同按钮单击事件的方法之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.net MVC 5 应用程序中单击按钮时使用 JavaScript/jQuery 将用户重定向到页面

如何在 ASP.NET MVC 中通过 Ajax 提交表单?

通过调用 ASP.NET 按钮单击从 jQuery 模态对话框回发

在 PostBack (ASP.NET) 上运行 jQuery 函数

使用 ASP.NET 表单身份验证的用户模拟

在按钮单击文本框值是空的使用 asp.net mvc 显示警报?