C# .NET5/MVC6中的异步路由约束(或其他约束)
我需要创建一个路由约束,但是这个约束需要使用我的一个服务,并且这个服务方法使用异步 现在,理想情况下,从这个routeConstraint返回的数据,我希望传递给控制器,以便在被调用的操作中使用,如果约束已经满足 用户将调用带有额外参数的控制器,我们将调用myName。如果该值出现在数据库中,我希望该记录出现在控制器方法中 调用控制器的路径看起来是这样的,其中data是我的控制器的名称,myName是一个字符串,我需要检查它是否存在于数据库中 如果myName不存在,则不应调用控制器。如果是,则应调用该方法,但myName值可用 不确定我是否需要使用其他的路径约束 注意:C# .NET5/MVC6中的异步路由约束(或其他约束),c#,asp.net,.net,asp.net-mvc,asp.net-core-mvc,C#,Asp.net,.net,Asp.net Mvc,Asp.net Core Mvc,我需要创建一个路由约束,但是这个约束需要使用我的一个服务,并且这个服务方法使用异步 现在,理想情况下,从这个routeConstraint返回的数据,我希望传递给控制器,以便在被调用的操作中使用,如果约束已经满足 用户将调用带有额外参数的控制器,我们将调用myName。如果该值出现在数据库中,我希望该记录出现在控制器方法中 调用控制器的路径看起来是这样的,其中data是我的控制器的名称,myName是一个字符串,我需要检查它是否存在于数据库中 如果myName不存在,则不应调用控制器。如果是,
我无法将其作为参数添加到此控制器中的每个方法,因此请不要建议它。您可以实现自己的
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
执行以下操作:
IRouter
(通常是MvcRouteHandler
)GetVirtualPath
执行以下操作:
RouteAsync
中的逻辑完全相反,因此我们生成匹配的相同URLUrlHelper
的任何调用的虚拟路径,例如ActionLink
和RouteLink
发出的调用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;
}
}
}
公共异步任务RouteAsync(RouteContext上下文)
{
//请求路径是整个路径(不带查询字符串)
//从正斜杠开始。
//示例:/Home/About
var requestPath=context.HttpContext.Request.Path.Value;
如果(!requestPath==)
{
//条件不匹配,返回此处将
//告诉框架此路由不匹配,然后
//它将自动调用下一条路线。
//这类似于从管线约束返回“false”。
返回;
}
//调用MVC控制器/操作。
//我们使用路由数据的副本,以便可以恢复
//与原文一致。
var oldRouteData=context.RouteData;
var newRouteData=新路由数据(旧路由数据);
newRoutedData.Routers.Add(_目标);
//TODO:在构造函数中或基于数据结构设置此选项。
newRoutedData.Values[“controller”]=“Custom”;
newRoutedData.Values[“action”]=“Details”;
//在此处设置任何其他管线值(如“id”)
尝试
{
context.RouteData=newRouteData;
//这里我们异步调用嵌套路由。
//嵌套路由通常应该是
//MvcRouteHandler。
//调用它类似于从
//路由约束。
wait_target.RouteAsync(上下文);
}
最后
{
//恢复原始值以防止污染管线数据。
如果(!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();
}
}