【问题标题】:how to add this code on a self hosted api?如何在自托管 api 上添加此代码?
【发布时间】:2016-02-17 21:01:37
【问题描述】:

根据这个问题,我无法在 Windows 服务上自行处理 Web api 时实现 IHttpModule

Is there a way to add an httpModule when webApi is running with the HttpSelfHostServer?

但是,我仍然需要在我的自托管 Web api 中的某处添加此代码。 我发现了这个关于如何解决这个问题的博客: http://www.silver-it.com/node/182

代码如下,但是我不能在自己托管的 API 上实现 IhttpModule

public class CORSPreflightModule : IHttpModule
    {
        private const string OPTIONSMETHOD = "OPTIONS";
        private const string ORIGINHEADER = "ORIGIN";
        private const string ALLOWEDORIGIN = "https://yourspodomain.sharepoint.com";
        void IHttpModule.Dispose()
        {

        }
        void IHttpModule.Init(HttpApplication context)
        {                 
            context.PreSendRequestHeaders += (sender, e) =>
            {
                var response = context.Response;

                if (context.Request.Headers[ORIGINHEADER] == ALLOWEDORIGIN)
                {
                    response.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");                    
                    response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");                                        
                }
                if (context.Request.HttpMethod.ToUpperInvariant() == OPTIONSMETHOD && context.Request.Headers[ORIGINHEADER] == ALLOWEDORIGIN)
                {
                    response.Headers.Clear();
                    response.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
                    response.Headers.Add("Access-Control-Allow-Origin", "https://yourspodomain.sharepoint.com");
                    response.Headers.Add("Access-Control-Allow-Credentials", "true");
                    response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
                    response.Clear();
                    response.StatusCode = (int)HttpStatusCode.OK;
                }                                                             
            };

        }        

    }

我的自托管 web api 是这样的:

程序.cs

static void Main()
{
    try
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new APIServiceTest()
        };
        ServiceBase.Run(ServicesToRun);
    }
    catch (Exception ex)
    {
        throw ex;
    }
}


class Startup
    {
        //  Hack from https://stackoverflow.com/a/17227764/19020 to load controllers in 
        //  another assembly.  Another way to do this is to create a custom assembly resolver
        //Type valuesControllerType = typeof(OWINTest.API.ValuesController);

        // This code configures Web API. The Startup class is specified as a type
        // parameter in the WebApp.Start method.
        public void Configuration(IAppBuilder appBuilder)
        {
            try
            {
                //Debugger.Launch();
                // Configure Web API for self-host. 
                HttpConfiguration config = new HttpConfiguration();

                config.MessageHandlers.Add(new CustomHeaderHandler());
                var corsAttr = new EnableCorsAttribute(System.Configuration.ConfigurationManager.AppSettings["DominioSharePoint"].ToString(), "*", "*");
                config.EnableCors(corsAttr);

                //  Enable attribute based routing
                //  http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
                config.MapHttpAttributeRoutes();

                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );

                appBuilder.UseWebApi(config);
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
    }

我的控制器:

 [EnableCors(origins: "https://xx.sharepoint.com", headers: "*", methods: "*")]
    public class CuentasCobroController : ApiController
    {

但是,由于它是自托管的,因此我无法在上面实现 IHttpModule,但我可以创建自定义处理程序,如何在自定义处理程序中从博客中实现上述代码?

public class CustomHeaderHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            return base.SendAsync(request, cancellationToken)
                .ContinueWith((task) =>
                {
                    HttpResponseMessage response = task.Result;
                    response.Headers.Add("Access-Control-Allow-Origin", "*");
                    return response;
                });
        }
    }

问题是,如何将第一个代码集成到我的 Windows 服务的启动中?

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-web-api


    【解决方案1】:

    使用DelegatingHandler 而不是IHttpModule,您就快到了。

    config.MessageHandlers.Add(new CorsHeaderHandler());
    

    DelegatingHandler.SendAsync 可以访问请求和响应。

    public class CorsHeaderHandler : DelegatingHandler
    {
        private const string OPTIONSMETHOD = "OPTIONS";
        private const string ORIGINHEADER = "ORIGIN";
        private const string ALLOWEDORIGIN = "https://yourspodomain.sharepoint.com";
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            return base.SendAsync(request, cancellationToken).ContinueWith(task =>
            {
                var allowedOrigin = request.Headers.Any(t => t.Key == ORIGINHEADER && t.Value.Contains(ALLOWEDORIGIN));
                if (allowedOrigin == false) return task.Result;
    
                if (request.Method == HttpMethod.Options)
                {
                    var emptyResponse = new HttpResponseMessage(HttpStatusCode.OK);
                    emptyResponse.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
                    emptyResponse.Headers.Add("Access-Control-Allow-Origin", ALLOWEDORIGIN);
                    emptyResponse.Headers.Add("Access-Control-Allow-Credentials", "true");
                    emptyResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
                    return emptyResponse;
                }
                else
                {
                    task.Result.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
                    task.Result.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
                    return task.Result;
                }
            });
        }
    }
    

    【讨论】:

      【解决方案2】:

      简单地说,您不能将IHttpModule 与自托管 Web API 或任何非 IIS 一起使用。 IHttpModule 只是一个 IIS 概念。

      正如您所发现的,您可以改为修改 Web API 管道并在其中插入您的代码(或等效的 Web API)。这可以通过DelegatingHandler 或操作过滤器来完成。

      然而,最简单的解决方案是简单地使用Microsoft.AspNet.WebApi.Cors NuGet 包。使用HttpConfiguration 对象,调用.EnableCors(...) 并按照来自Microsoft 的the instructions here 传入EnableCorsAttribute 对象。

      这是您在上面的代码中已经完成的操作,但您似乎还尝试从 HTTP 模块中添加自定义 CORS 代码。如果您从控制器中删除 EnableCors 属性,并删除您的 CustomHeaderHandler,它应该可以正常工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-04
        • 2010-09-18
        • 2015-04-08
        • 2010-12-10
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        相关资源
        最近更新 更多