如何在自托管api上添加此代码?

时间:2016-02-17 21:01:37

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

根据这个问题,我在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

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;
            }

        }
    }

我自己托管的网络API如下:

Program.cs的

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

我的控制器:

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;
                });
        }
    }

然而,因为它的自托管我不能实现IHttpModule,如上所述,但我可以创建一个自定义处理程序如何从自定义处理程序中的博客实现上面的代码?

{{1}}

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

2 个答案:

答案 0 :(得分:3)

使用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;
            }
        });
    }
}

答案 1 :(得分:1)

简而言之,您不能将IHttpModule与自托管Web API或任何非IIS使用。 IHttpModule仅是IIS概念。

您可以做的是,您可以修改Web API管道并在那里插入代码(或Web API等效代码)。这可以使用DelegatingHandler或操作过滤器来完成。

然而,最简单的解决方案是简单地使用Microsoft.AspNet.WebApi.Cors NuGet包。使用HttpConfiguration对象,请致电.EnableCors(...)并根据the instructions here从Microsoft传入EnableCorsAttribute个对象。

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