Async RouteBase в ASP.NET с GetRouteDataAsync и GetVirtualPathAsync?

У меня есть настраиваемый маршрут ASP.NET, в котором есть операции ввода-вывода. Пока предположим, что эти операции ввода-вывода не могут быть кэшированы (т.е. Слишком большие).

В некотором смысле я ищу класс AsyncRouteBase с

public async override Task<RouteData> GetRouteDataAsync(HttpContextBase httpContext)
public async override Task<VirtualPathData> GetVirtualPathAsync(RequestContext requestContext, RouteValueDictionary routeValues);
  • Что-то подобное уже существует? (не может найти его)
  • Есть ли место в конвейере ASP.NET, где я могу создать это самостоятельно?

Я использую ASP.NET MVC 5.2.3.0

Ответ 1

Вы не можете создать AsyncRouteBase, потому что маршруты, используемые ASP.NET MVC, являются синхронными. Вы должны понимать, что для того, чтобы вы могли создавать асинхронные методы, кто-то должен использовать их асинхронно, вы не можете волшебным образом сделать все асинхронным, добавив метод async.

Маршрутизация не может быть асинхронной по разным причинам, Маршруты кэшируются и создаются только один раз при выполнении первого запроса. Остерегайтесь, маршруты кэшируются, они не будут меняться, и они не могут быть изменены во время выполнения, потому что они выполняются первыми, если Routing будет выполнять вызовы async db, каждый запрос должен будет дождаться выполнения условия маршрутизации, что приведет к замедлению всего приложения.

И вам в основном не нужен AsyncRouteBase, вместо этого вы можете создать Async Route Handler.

public class AsyncRouteHandler : IRouteHandler
{
    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
    {
        return new AsyncHttpHandler();
    }
}

public class AsyncHttpHandler : HttpTaskAsyncHandler{
    public override async Task ProcessRequestAsync(HttpContext context)
    {        
    }
}

Однако использование MVC-конвейера внутри этого потребует много работы, но вы можете легко игнорировать это и обслуживать свой ответ здесь. Вы можете использовать контроллер factory внутри этого и создать свои методы для выполнения того, что вам нужно.

Другой альтернативой является простое использование MEF или другой формы DI для управления вашей большей базой кода и вызова соответствующих методов внутри AsyncHttpHandler.

Ответ 2

К сожалению, нет способа переопределить метод async с async. Я считаю, что лучше всего иметь метод async non override и вызывать на него не из async, например:

public override RouteData GetRouteData(HttpContextBase httpContext) {
    return GetRouteDataAsync(httpContext);
    //return await GetRouteDataAsync(httpContext);
}

public async override Task<RouteData> GetRouteDataAsync(HttpContextBase httpContext){
    //operations here
}

Примечание: это может вызвать проблемы. Если исходный код не ожидал, что какой-либо код async, который будет выполняться при введении этого шаблона, может превзойти ожидания. Избегайте его, если это возможно.

Как совет, см. Упростить асинхронное программирование с задачами