ug环球客户端:.NET Core请求控制器Action方式准确匹配,但为何404?

admin 3个月前 (06-25) 科技 34 0

前言

有些刻我们会发现方式名称都准确匹配,但就是找不到对应请求接口,以是本文我们来深入了解下何时会泛起接口请求404的情形。

匹配控制器Action方式(404)

首先我们建立一个web api应用程序,我们给出如下示例控制器代码

[ApiController]
[Route("[controller]/[action]")]
public class WeatherController : ControllerBase
{
    [HttpGet]
    string Get()
    {
        return "Hello World";
    }
}

&NBsp;

当我们举行如上请求时会发现接口请求不到,这是为何呢?仔细的你应该可能发现了,对于请求方式是私有,而不是公共的,当我们加上public就可以请求到了接口

[HttpGet("get")]
public string Get()
{
    return "Hello World";
}

匹配控制器Action方式本质

经由如上示例,那么对于Action方式的到底要知足怎样的界说才能够不至于请求不到呢?接下来我们看看源码怎么讲。我们找到DefaultApplicationModelProvider类,在此类中有一个OnProvidersExecuting方式用来构建控制器和Action方式模子,当我们构建完毕所有知足条件的控制器模子后,紧接着势必会遍历控制器模子去获取对应控制器模子下的Action方式,这里只截取获取Action方式片断,源码如下:

foreach (var controllerType in context.ControllerTypes)
{    
    //获取控制器模子下的Action方式
    foreach (var methodInfo in controllerType.AsType().GetMethods())
    {
        var actionModel = CreateActionModel(controllerType, methodInfo);
        if (actionModel == null)
        {
            continue;
        }

        actionModel.Controller = controllerModel;
        controllerModel.Actions.Add(actionModel);    
    }
}

上述红色符号则是建立Action模子的重点,我们继续往下看到底知足哪些条件才建立Action模子呢?

protected virtual ActionModel CreateActionModel(TypeInfo typeInfo, MethodInfo methodInfo)
{
    if (typeInfo == null)
    {
        throw new ArgumentNullException(nameof(typeInfo));
    }

    if (methodInfo == null)
    {
        throw new ArgumentNullException(nameof(methodInfo));
    }

    if (!IsAction(typeInfo, methodInfo))
    {
        return null;
    }    
    ......    
}

到了这个方式内里,我们找到了若何确定一个方式为Action方式的源头,由于该方式有点长,这里我接纳文字叙述来作为判断逻辑,如下:

protected virtual bool IsAction(TypeInfo typeInfo, MethodInfo methodInfo)
{
    //若是有属性接见器(无效)

    //若是有NonAction特征标识无效)

    //若是重写Equals(Object), GetHashCode()方式(无效)

    //若是实现Dispose方式(无效)

    //若是是静态方式(无效)

    //若是是抽象方式(无效)

    //若是是组织函数(无效)

    //若是是泛型方式(无效)

    //必须为公共方式
    return methodInfo.IsPublic;
}

如上是从方式界说的角度来过滤而获取Action方式,除此之外,我们请求方式的名称还可以自界说,好比通过路由、ActionName特征指定,那么这二者是否存在优先级呢?好比如下示例:

[ApiController]
[Route("[controller]/[action]")]
public class WeatherController : ControllerBase
{
    [HttpGet]
    [ActionName("get1")]
    public string get()
    {
        var routeValue = HttPContext.Request.RouteValues.FirstOrDefault();

        return routeValue.Value.ToString();
    }
}

我们可以看到此时将以ActionName特征作为方式名称。以是在上述过滤方式界说后最先构建方式模子,在此之后还会再做一步操作,那就是查找该方式是否通过ActionName特征标识,若存在则以ActionName特征标识给定的名称作为请求方式名称,否则以方式界说名称为准,源码如下:

var actionModel = new ActionModel(methodInfo, attributes);

AddRange(actionModel.Filters, attributes.OfType<IFilterMetadata>());

var actionName = attributes.OfType<ActionNameAttribute>().FirstOrDefault();
if (actionName?.Name != null)
{
    actionModel.ActionName = actionName.Name;
}
else
{
    actionModel.ActionName = methodInfo.Name;
}

还没完,若是将路由特征放到Action方式上,如下,此时请求接口应该是weather/get照样weather/get1呢?

[ApiController]
public class WeatherController : ControllerBase
{
    [HttpGet]
    [Route("weather/get")]
    [ActionName("get1")]
    public string get()
    {
        var routeValue = HttpContext.Request.RouteValues.FirstOrDefault();

        return routeValue.Value.ToString();
    }
}

此时若我们以weather/get1请求将泛起404,照样以路由特征模板给定为准举行请求,但最终会将路由上Action方式名称通过ActionName特征上的名称赋值给Action模子中的ActionName举行笼罩,源码如下,以是上述我们获得的action名称为get1,,固然这么做没有任何实际意义。

public static void AddRouteValues(ControllerActionDescriptor actionDescriptor,ControllerModel controller,ActionModel action)
{
    foreach (var kvp in action.RouteValues)
    {
        if (!actionDescriptor.RouteValues.ContainsKey(kvp.Key))
        {
            actionDescriptor.RouteValues.Add(kvp.Key, kvp.Value);
        }
    }

    if (!actionDescriptor.RouteValues.ContainsKey("action"))
    {
        actionDescriptor.RouteValues.Add("action", action.ActionName ?? string.Empty);
    }

    if (!actionDescriptor.RouteValues.ContainsKey("controller"))
    {
        actionDescriptor.RouteValues.Add("controller", controller.ControllerName);
    }
}

总结

本文我们只是单独针对查找Action方式名称匹配问题做了进一步的探讨,凭据源码剖析,对Action方式名称指定会做3步操作:第一,凭据方式界说举行过滤筛选,第二,若方式通过AcionName特征标识则以其所给名称为准,否则以方式名称为准,最终赋值给ActionModel上的ActionName属性,第三,将ActionModel上的ActionName值赋值给路由聚集中的键Action。

,

联博

www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。

AllBetGaming声明:该文看法仅代表作者自己,与本平台无关。转载请注明:ug环球客户端:.NET Core请求控制器Action方式准确匹配,但为何404?

网友评论

  • (*)

最新评论

站点信息

  • 文章总数:809
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1375
  • 评论总数:346
  • 浏览总数:28448