. net 5/MVC6中的异步路由约束(或其他东西)

本文关键字:其他 约束 路由 MVC6 异步 net | 更新日期: 2023-09-27 18:17:19

我需要创建一个路由约束,但是这个约束需要使用我的一个服务,而这个服务方法使用async。

现在,理想情况下,从这个routeconconstraint返回的数据,我想传递给控制器,以便在正在调用的操作中使用,如果约束已经满足。

用户将调用带有额外参数的控制器,我们将调用myName。如果这个值出现在数据库中,我希望这个记录在控制器方法中。

调用控制器的路径看起来像这样,其中data是我的控制器的名称,myName是一个字符串,我需要检查它是否存在于数据库中。

http://localhost/api/data/myName

如果myName不存在,控制器不应该被调用。如果是,则应该调用该方法,但要使用myName值。

不确定是否可能我需要使用其他东西然后路由约束?

注意:

. net 5/MVC6中的异步路由约束(或其他东西)

我不能将此作为该控制器中每个方法的参数添加,因此请不要建议。

您可以实现自己的IRouter,由MVC6异步解析。IRouter是每条路由实现的接口,所以你在较低的层次上操作。

namespace Microsoft.AspNet.Routing
{
    public interface IRouter
    {
        // Populates route data (including route values) based on the
        // request
        Task RouteAsync(RouteContext context);
        // Derives a virtual path (URL) from a list of route values
        VirtualPathData GetVirtualPath(VirtualPathContext context);
    }
}

RouteAsync执行以下操作:

  1. 分析请求是否与路由匹配。
  2. 如果有匹配,设置路由值。
  3. 如果我们有一个匹配,传递调用到下一个IRouter(通常是MvcRouteHandler)。

GetVirtualPath执行以下操作:

  1. 比较一组路由值,看它们是否匹配路由。
  2. 如果匹配,则将路由值转换为虚拟路径(URL)。这通常应该与RouteAsync中的逻辑完全相反,因此我们生成匹配的相同URL。
  3. 框架返回对UrlHelper的任何调用的虚拟路径,例如ActionLinkRouteLink
RouteAsync的典型实现是这样的:
public async Task RouteAsync(RouteContext context)
{
    // Request path is the entire path (without the query string)
    // starting with a forward slash.
    // Example: /Home/About
    var requestPath = context.HttpContext.Request.Path.Value;
    if (!requestPath == <some comparison (slice the string up if you need to)>)
    {
        // Condition didn't match, returning here will
        // tell the framework this route doesn't match and
        // it will automatically call the next route.
        // This is similar to returning "false" from a route constraint.
        return;
    }
    // Invoke MVC controller/action.
    // We use a copy of the route data so we can revert back
    // to the original.
    var oldRouteData = context.RouteData;
    var newRouteData = new RouteData(oldRouteData);
    newRouteData.Routers.Add(_target);
    // TODO: Set this in the constructor or based on a data structure.
    newRouteData.Values["controller"] = "Custom"; 
    newRouteData.Values["action"] = "Details";
    // Set any other route values here (such as "id")
    try
    {
        context.RouteData = newRouteData;
        // Here we are calling the nested route asynchronously.
        // The nested route should generally be an instance of
        // MvcRouteHandler.
        // Calling it is similar to returning "true" from a
        // route constraint.            
        await _target.RouteAsync(context);
    }
    finally
    {
        // Restore the original values to prevent polluting the route data.
        if (!context.IsHandled)
        {
            context.RouteData = oldRouteData;
        }
    }
}

请参阅此处的答案和此处的其他示例

我建议您使用AsyncActionFilter用于此目的。

假设你的路由模板:{controller}/{action}/{myName}

实现AsyncActionFilter:

using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Framework.Internal;
namespace ActionFilterWebApp.Filters
{
    public class ThirdPartyServiceActionFilter : ActionFilterAttribute
    {
        public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var routeKey = "myName";
            var routeDataValues = context.RouteData.Values;
            var allowActionInvoke = false;
            if (routeDataValues.ContainsKey(routeKey))
            {
                var routeValue = routeDataValues[routeKey];
                //allowActionInvoke = ThirdPartyService.Check(routeValue);
            }
            if (!allowActionInvoke)
            {
                //if you setting up Result property - action doesn't invoke
                context.Result = new BadRequestResult();
            }
            return base.OnActionExecutionAsync(context, next);
        }
    }
}

在控制器上添加ThirdPartyServiceActionFilter:

   [ThirdPartyServiceActionFilter]
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }