为啥我在 Global.asax.cs 中的 Application_BeginRequest 没有被自托管的 WCF 服务调用

Posted

技术标签:

【中文标题】为啥我在 Global.asax.cs 中的 Application_BeginRequest 没有被自托管的 WCF 服务调用【英文标题】:Why is my Application_BeginRequest in Global.asax.cs not getting called with a self hosted WCF service为什么我在 Global.asax.cs 中的 Application_BeginRequest 没有被自托管的 WCF 服务调用 【发布时间】:2020-10-21 00:19:58 【问题描述】:

我正在自行托管需要支持入站 CORS REST 流量的 WCF 服务。所以我添加了带有以下代码块的 Global.asax.cs 文件,但 Application_BeginRequest() 永远不会触发。我也在我的 app.Config 中设置了。还有什么我需要做的吗?这适用于自托管服务还是仅通过 IIS 托管的服务?

    protected void Application_BeginRequest(object sender, EventArgs e)
    
        string origin = HttpContext.Current.Request.Headers["origin"];
        if (!String.IsNullOrEmpty(origin)) // CORS origin?
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", origin);

        if (HttpContext.Current.Request.HttpMethod == "OPTIONS") // CORS origin w/ options?
        
            var requestedHeaders = HttpContext.Current.Request.Headers["Access-Control-Request-Headers"];
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", requestedHeaders);
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.StatusCode = 200;
            HttpContext.Current.Response.End();
        
    

【问题讨论】:

【参考方案1】:

只有托管在 IIS 上的全局文件才会生效。 IIS 将 WCF 服务视为 Web 服务来解析其全局文件。如果是自托管的,全局文件将不会被解析和运行。

我们可以让WCF支持JSONP来解决跨域问题:

<binding name="bind1" crossDomainScriptAccessEnabled="true">
</binding>

你也可以实现IDispatchMessageInspector,在服务响应之前添加响应头。这个方案适合自托管。

public class ServerMessageLogger : IDispatchMessageInspector
    
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        
           return null;
        

        public void BeforeSendReply(ref Message reply, object correlationState)
        
            WebOperationContext ctx = WebOperationContext.Current;
            ctx.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
        
    

有关IDispatchMessageInspector的更多信息,请参考以下链接:

https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.dispatcher.idispatchmessageinspector?view=netframework-4.8

如果还不清楚,可以参考下面的链接,里面有完整的代码:

How to enable Cross-Origin Resource Sharing in .Net Console Application WCF Service?

更新

以下图片是我的demo:

上面两张图有一张使用了WebOperationContext,一张没有使用。

实际上,WebOperationContext 和 HttpContext 类似。 WebOperationContext 通常用于 WCF REST 方法中,HttpContext 通常用于 ASP.NET WebForms 页面或 ASMX Web Service Web 方法中。

【讨论】:

感谢您的帮助。在绑定中添加 crossDomainScriptAccessEnabled='true' 失败并抛出无法识别的属性 'crossDomainScriptAccessEnabled',因此不起作用。所以我实现了 IDispatchMessageInspector 方法。有没有好方法来测试服务在请求“选项”时报告正确的响应标头?我试过test-cors.org,但是当IDispatchMessageInspector返回响应头时它报告XHR状态:0 XHR状态文本:“”,也许没关系。不确定。现在只需要一种方法来验证服务是否支持 CORS 模式。 在我的更新中,我验证了此解决方案支持 CORS。 实现IDispatchMessageInspector接口后,我们需要将其应用到服务中。详情可以参考我给的第二个链接。

以上是关于为啥我在 Global.asax.cs 中的 Application_BeginRequest 没有被自托管的 WCF 服务调用的主要内容,如果未能解决你的问题,请参考以下文章

MVC4 中 Global.asax.cs 页面中的问题

MVC 应用程序 - 从 Global.asax.cs 检索 LoaderExceptions

Global.asax.cs 为 /.aspx 执行子请求时出错。 Server.Transfer

ASP.NET MVC:如何在 Global.asax.cs 中的 Application_Start() 中检测浏览器宽度

Global.asax.cs介绍

在 global.asax.cs 中分配后未填充 Insights InstrumentationKey