【问题标题】:How can an OWIN Startup method get the base URL of the web site?OWIN 启动方法如何获取网站的基本 URL?
【发布时间】:2021-09-16 23:40:29
【问题描述】:

OWIN启动方法如何获取网站的基本URL?

我正在尝试编写在使用 IISExpress 进行调试、使用自托管和在 IIS 下进行单元测试时可以使用的代码。

自托管时,我可以在 IAppBuilder.Properties["host.Addresses"] 中找到此信息,但在 IISExpress 下运行时不存在(尚未检查 IIS)。

【问题讨论】:

  • Afaik,这是不可能通过托管 c# 代码实现的。仅仅因为 IISExpress 和您的程序集被划分在不同的进程中,您构建的 Owin 程序集是 IISExpress 的子进程。它只能读取环境中的变量。 “绑定”和“监听”通过 IISExpress(虚拟路径、端口和主机过滤等)处理。在您手头有请求(然后使用中间件)之前,您没有关于 ServerRequestResponse 的详细信息。询问您是否需要详细信息

标签: c# owin


【解决方案1】:
System.Web.VirtualPathUtility.ToAbsolute("~")

【讨论】:

  • 自托管时抛出异常,消息为:“应用程序相对虚拟路径'~'不能设为绝对,因为应用程序的路径未知。”
【解决方案2】:

我保留这篇文章是为了说明不要走我提供的道路。很容易看出这个答案是如何解决未经训练的眼睛的。

(编辑:2016 年 10 月 6 日)

好的,所以这篇文章下面的对话并没有帮助我理解我为什么错了。所以我问了朋友、同事,最后从当地社区得到了一个很好的答案,我参与其中,以更多地解释对话以及为什么这个答案还不够。有人提到,下面不回答基本 URL 的启动应用程序请求,它回答了如何使用请求处理检索获取所请求应用程序的基本 URL。不同之处在于,请求处理在每次请求时获取基本 URL;而从启动应用程序中获取基本 URL 只发生一次,并且仅在应用程序启动时才保留请求的应用程序的值。

老实说,我还没有看到或查看任何类型的文档,可让您在当前请求处理方案之外检索基本 URL。我也不确定在 .NET 堆栈的当前状态下是否有可能。再次,对于没有指出这一点并对解决方案感到困惑,我深表歉意。

对于那些仍然想使用解决方法从请求的应用程序(可能来自启动应用程序..或其他类型的外部应用程序)获取基本 url 并且不介意每次获取它的人请求,并且不介意稍后将检索基本 URL 的时间点,下面的解决方案回答了这个问题。

(原方案)

这是一篇很好的文章,解释了如何使用 Owin 中间件管道:

http://blog.2mas.xyz/owin-middleware/

您可以使用 app.Run 接受上下文,或者 app.Use 接受上下文,然后使用 Func 类型的 next(获取管道中的下一步)。

public void Configuration(IAppBuilder app)
{
    JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
    //First way using app.Use
    var currentUri1 = "";
    app.Use((context, next) => { 
        currentUri1 = context.Request.Uri.ToString(); //Get base URL
        return next().ContinueWith(task =>
        {
            context.Response.WriteAsync(" FINISHED RETRIEVING CURRENT URL ");
        });
    });
    
    //Second way using app.Run
    var currentUri2 = "";
    app.Run((context) => { 
        currentUri2 = context.Request.Uri.ToString(); //Get base URL
         var task = context.Response.WriteAsync("Hello world! " + context.Request.Path);
            return task;
    });
}

context.Request 本质上是传入请求的包装器,它的类型为 IOwinRequest。更多信息可以在这里找到:IOwinRequest Interface

IOwinRequest 的 Uri 属性是 System.Uri 类型,所以你可以在这里查看 Uri 附带的哪些属性(如主机、端口、绝对 url、查询变量等):Uri Class

[编辑回应评论]

如果您真的不相信 context.Request 在启动时可用,请查看此流程:

IOwinContext,它“包装 OWIN 环境字典并提供强类型访问器”,它有一个名为 IOwinRequest 的属性,它“获取一个暴露请求特定属性的包装器”。它是Microsoft.Owin.IOwinRequest 类型,本质上具有Uri 属性

【讨论】:

  • 我看不出这对获取网站的基本 URL 有何帮助。
  • Use 和 Run 方法将处理程序添加到管道中,当请求进入时会被调用。context.Request 在启动时不可用。
  • 是的,我确实读过文献。 Use 和 Run 方法添加了在请求进来时调用的处理程序。它们在启动时不会被调用。启动时没有可用的 IOwinContext。
  • @sksallaj 但你没有[在启动期间使用上下文]。您在处理程序中使用它。我想你可能对 lambda 语法感到困惑; “内部”代码不会与 Configuration 方法同时执行(如果您停下来想想这些 Use*/Run 方法的含义,这应该很明显)。
  • app.Use 或 app.Run 将中间件插入 Owin 管道。它们在启动函数执行期间不执行。您正在为将在每个请求期间设置的变量创建一个闭包(线程问题?)。提问者希望在启动执行时获取基本 URL
【解决方案3】:

对于 vNext 下的任何人,试试这个:

public void Configure(IApplicationBuilder app)
        {
            app.Use(async (ctx, next) =>
            {
                var hostingEnvironment = app.ApplicationServices.GetService<IHostingEnvironment>();
                var realPath = hostingEnvironment.WebRootPath + ctx.Request.Path.Value;

                // do something with the file

                await next();
            });

        }

如果您不在 vnext 下,我确实在 vNext / dnx 下看到了这个对我不起作用的答案:https://stackoverflow.com/a/24747658/486028

Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase)

在 dnx 下,这只是游戏我包含 .dnx 运行时的文件夹,但可能在其他上下文中工作

【讨论】:

  • 你激动了一分钟,因为:“app.ApplicationServices.GetService();”看起来很有希望。但是,后来我意识到它是 ASP.NET vNext 的 IApplicationBuilder 接口的一部分。我正在使用当前版本。
  • @john vottero,是的,我的代码用于 vnext。已更新我的答案以明确说明。
猜你喜欢
  • 2012-09-16
  • 2020-08-25
  • 2016-12-12
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 2014-03-25
  • 2019-02-09
相关资源
最近更新 更多