Перезаписать базовые c функциональные возможности отображения действий и параметров в. net веб-API - PullRequest
3 голосов
/ 08 января 2020

Я хотел бы закодировать URL (исключая источник) всех запросов к Base64. Всякий раз, когда делается запрос, он должен декодировать URL, найти соответствующий контроллер и действие и вызвать его с соответствующими параметрами.

Есть ли функция, которую я могу перезаписать (возможно, в global.asax или webapiconfig.cs) что будет вызываться всякий раз, когда делается запрос?

1 Ответ

6 голосов
/ 12 января 2020

Предполагая, что вы работаете с asp. net mvc и со всем модным. net ядро ​​промежуточного программного обеспечения еще не вещь, вы можете посмотреть на пользовательский handler. Теоретически вы можете написать код bootstrap непосредственно в global.asax, но, поскольку он по умолчанию вызывает WebApiConfig.Register ():

 GlobalConfiguration.Configure(WebApiConfig.Register);

, это, вероятно, лучшее место для вещей, связанных с WebAPI.

App_Start / WebApiConfig.cs

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

и затем определите ваш обработчик:

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

В зависимости от того, что именно вы хотите ваш обработчик, вы можете обнаружить, что вам также придется предоставить свою собственную ControllerSelector реализацию:

WebApiConfig.cs

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

MyControllerSelector.cs

    public class MyControllerSelector : DefaultHttpControllerSelector
    {
        public MyControllerSelector(HttpConfiguration configuration) : base(configuration)
        {
        }

        public override string GetControllerName(HttpRequestMessage request)
        {
            //this is pretty minimal implementation that examines a header set from TestHandler and returns correct value
            if (request.Headers.TryGetValues("controllerToCall", out var candidates))
                return candidates.First();
            else
            {
                return base.GetControllerName(request);
            }
        }
    }

Я не знаю достаточно о вашей конкретной c среде, так что это далеко не полное решение, но, надеюсь, оно очерчивает один путь для изучения

...