在没有请求的情况下 asp.net Web 表单自定义类中创建相对 URL



我实现了某种调用函数ProcessJob的作业调度。现在在这种方法中,我需要生成我的一个页面的网址,即DoanloadPage.aspx?some_params。该 URL 通过电子邮件发送给用户,当用户单击该链接时,它将转到该页面。

这里的问题是我没有在 Web 请求方法中生成 url,或者我无权访问请求对象。URL 需要在线程化的自定义类中生成,即不在 Web 请求中生成。

所以我不能使用这些解决方案:

HostingEnvironment.MapPath("test.aspx");
VirtualPathUtility.ToAbsolute("123.aspx");
HttpContext.Current.Request.Url.Authority;

这些都不起作用,因为我认为它们都以某种方式依赖于当前的请求或会话。那么,如何在代码中为我的应用程序生成 url,以便我可以随心所欲地使用它们。

如果您的方法无法使用HttpContext.Current.Request.Url,例如,如果是后台计划任务,则可以使用以下任一选项:

  • 如果您的代码托管在同一 ASP.NET 应用程序中,则可以在第一个请求中将站点的站点域名传递给您的类。为此,您需要处理Application_BeginRequest事件并从HttpContext.Current.Request.Url获取域,然后将其传递给类,或将其存储在应用程序范围的存储中。您可以在这篇文章或原始文章中找到实现。
    注意:该代码在SO中可用,因此我不会重复代码 这里。

  • 如果您的代码未托管在同一个 ASP.NET 应用程序中,或者出于任何原因您不想依赖Application_BeginRequest,作为另一种选择,您可以将站点域名存储在设置中(例如 app.condig 中的 appsettigs 或 web.config,如果是 Web 应用程序)并在您的代码中使用它。

你可以做这样的事情。Dns.GetHostName 将返回托管站点的计算机的名称。您可以使用它来检查站点是否在开发服务器上。

string domain = "www.productionurl/123.aspx";
if (Dns.GetHostName() == "Development")
{
domain = "www.developmenturl/123.aspx";
}

Dns.GetHostName()不是唯一的检查方法。您也可以使用HostingEnvironment.ApplicationPhysicalPath。您也可以检查并查看路径是否是开发服务器的路径。

我的回答是:不要这样做。您正在构建一个分布式系统,尽管很简单,一般来说,在分布式系统中引入服务之间的耦合是有问题的。因此,即使可以使用Application_BeginRequest为您的域设定种子,您也会将批处理作业的行为绑定到您的网站。通过这种安排,您可能会传播错误,并使系统的部署更加复杂。

查看此问题的更好方法是意识到核心愿望是将生产站点的绑定与批处理作业中使用的 URL 同步。在许多情况下,批处理的 app.config 中的条目将是最佳解决方案,除非您知道您的 URL 将频繁更改或需要扩展到许多不同的任意 URL,否则实际上不需要引入代码。如果您需要支持以编程方式更改 URL,我建议您考虑设置分布式配置系统(如 Consul),并从部署系统中读取批处理的 IIS 绑定和 app.config 文件的当前 URL。因此,即使在此高级方案中,批处理和网站之间也没有直接交互。

最新更新