ApiControllerActionSelector等效于Asp .net MVC核心

时间:2017-04-21 10:48:06

标签: asp.net-web-api asp.net-core-mvc

我们正在从web api迁移到asp .net mvc核心,我在web api中有一个动作选择器,其中如果存在url“$”符号中的任何软件,我们用来调用控制器中的特定方法。 我们使用ApiControllerActionSelector在web api中实现的这个功能是在web api中做同样的代码 -

public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext) {
           string urlDecode = HttpUtility.UrlDecode(
               controllerContext.Request.RequestUri.ToString());
           if (urlDecode != null && urlDecode.Contains("$")) {
               if (controllerContext.Request.Method == HttpMethod.Post) {
                   MethodInfo method = controllerContext.ControllerDescriptor.ControllerType
                       .GetMethod(
                           "PostCustomOperation");
                   return
                       new ReflectedHttpActionDescriptor(
                           controllerContext.ControllerDescriptor, method);
               }
               if (controllerContext.Request.Method == HttpMethod.Get) {
                   MethodInfo method = controllerContext.ControllerDescriptor.ControllerType
                       .GetMethod(
                           "GetCustomOperation");
                   return
                       new ReflectedHttpActionDescriptor(
                           controllerContext.ControllerDescriptor, method);
               }
           }
           HttpActionDescriptor result = base.SelectAction(controllerContext);
           return result;
       }

我无法找到在Asp .net mvc核心中执行相同操作的等效方法,我尝试实现IRouter但是我们必须指定控制器,但我不知道。 关于如何在Asp.net MVC核心中实现相同或不可能的任何建议?

2 个答案:

答案 0 :(得分:1)

你想要的是uploadImage(fileToUpload: any) : Observable<any> { let input = new FormData(); input.append("image", fileToUpload); return this.http.post('http://Api.app/api/v1/upload', input) .map( (response: Response) => { // I was missing this part response.json() } ); } 。您可以在ConfigureServices IActionSelector中为其注册实现。默认实现是services.AddSingleton<IActionSelector, CustomActionSelector>(),您可以在自定义实现中委托它。

答案 1 :(得分:0)

我选择替换IActionInvokerFactory。它更短。这是实现。然后,我创建自己的IActionInvoker包装器。

我的目标是在必要时再次调用控制器操作。

public class PolicyActionInvokerFactory : IActionInvokerFactory
{
    private readonly IEFConcurrencyService efConcurrencyService;
    private readonly IActionInvokerProvider[] actionInvokerProviders;

    public PolicyActionInvokerFactory(
        IEFConcurrencyService efConcurrencyService,
        IEnumerable<IActionInvokerProvider> actionInvokerProviders
    )
    {
        this.efConcurrencyService = efConcurrencyService;
        this.actionInvokerProviders = actionInvokerProviders.OrderBy(item => item.Order).ToArray();
    }

    public IActionInvoker CreateInvoker(ActionContext actionContext)
    {
        var context = new ActionInvokerProviderContext(actionContext);

        foreach (var provider in actionInvokerProviders)
        {
            provider.OnProvidersExecuting(context);
        }

        for (var i = actionInvokerProviders.Length - 1; i >= 0; i--)
        {
            actionInvokerProviders[i].OnProvidersExecuted(context);
        }

        return new RetryActionInvoker(efConcurrencyService, context.Result, actionContext);
    }

    class RetryActionInvoker : IActionInvoker
    {
        private readonly IEFConcurrencyService efConcurrencyService;
        private readonly IActionInvoker inner;
        private readonly ActionContext actionContext;

        public RetryActionInvoker(
            IEFConcurrencyService efConcurrencyService,
            IActionInvoker inner,
            ActionContext actionContext
        )
        {
            this.efConcurrencyService = efConcurrencyService;
            this.inner = inner;
            this.actionContext = actionContext;
        }

        public Task InvokeAsync()
        {
            var methodInfo = actionContext.ActionDescriptor;
            var shouldUseRetryLogic = methodInfo.EndpointMetadata.Any(m => m is RetryOnDbExceptionAttribute);
            if (shouldUseRetryLogic)
            {
                return efConcurrencyService.RetryOnError(() => {
                    // You will need to rewind the body here if you are using [FromBody]
                    // This is a little out of scope, but you should EnableBuffering()
                    // Then rewind the body with something like this:
                    // actionContext.HttpContext.Request.Body.Seek(0, System.IO.SeekOrigin.Begin);
                    return inner.InvokeAsync();
                });
            }

            return inner.InvokeAsync();
        }
    }
}