覆盖 .net Web API 中动作映射和参数的基本功能

nic*_*oum 3 .net c# asp.net-web-api

我想对 Base64 的所有请求的 URL(不包括来源)进行编码。每当发出请求时,它应该解码 URL,找到相应的控制器和操作,并使用相应的参数调用它。

是否有我可以覆盖(可能在global.asax或 中webapiconfig.cs)的函数,该函数将在发出请求时被调用?

tim*_*mur 6

假设您使用 asp.net mvc 并且所有花哨的 .net 核心中间件还不是一回事,您可以查看 custom handler. 理论上您可以直接在 中编写引导程序代码global.asax,但默认情况下它会调用 WebApiConfig.Register():

 GlobalConfiguration.Configure(WebApiConfig.Register);
Run Code Online (Sandbox Code Playgroud)

它可能是处理 WebAPI 的更好地方。

App_Start/WebApiConfig.cs

 GlobalConfiguration.Configure(WebApiConfig.Register);
Run Code Online (Sandbox Code Playgroud)

然后定义您的处理程序:

测试处理程序

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Web API routes
            config.MessageHandlers.Add(new TestHandler()); // if you define a handler here it will kick in for ALL requests coming into your WebAPI (this does not affect MVC pages though)
            config.MapHttpAttributeRoutes();
            config.Services.Replace(typeof(IHttpControllerSelector), new MyControllerSelector(config)); // you likely will want to override some more services to ensure your logic is supported, this is one example

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

            //a non-overlapping endpoint to distinguish between requests. you can limit your handler to only kick in to this pipeline
            config.Routes.MapHttpRoute(name: "Base64Api", routeTemplate: "apibase64/{query}", defaults: null, constraints: null
                //, handler: new TestHandler() { InnerHandler = new HttpControllerDispatcher(config) } // here's another option to define a handler
            );
        }
    }
Run Code Online (Sandbox Code Playgroud)

根据您希望 Handler 做什么,您可能会发现您还必须提供自定义ControllerSelector实现:

WebApiConfig.cs

// add this line in your Register method
config.Services.Replace(typeof(IHttpControllerSelector), new MyControllerSelector(config));
Run Code Online (Sandbox Code Playgroud)

我的控制器选择器.cs

    public class TestHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            //suppose we've got a URL like so: http://localhost:60290/api/VmFsdWVzCg==
            var b64Encoded = request.RequestUri.AbsolutePath.Remove(0, "/apibase64/".Length);
            byte[] data = Convert.FromBase64String(b64Encoded);
            string decodedString = Encoding.UTF8.GetString(data); // this will decode to values
            request.Headers.Add("controllerToCall", decodedString); // let us say this is the controller we want to invoke
            HttpResponseMessage resp = await base.SendAsync(request, cancellationToken);
            return resp;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我对您的特定环境了解不够,因此这远不是完整的解决方案,但希望它概述了一种供您探索的途径