一、异常描述
.Net core相关api接口报错404,找不到对应的接口路径
二、异常分析
DMS根站点配置了Url重写规则,具体规则见图2. url重写规则内容。这里会拦截所有/api开始的接口请求路径,并转发到http://192.168.160.28:5002/路径下,导致不同项目里的接口出现404错误。


三、解决方案
1. 定制个性化接口路径
这个方案延续使用了第二节里的配置方案,差别在于将你所需要的接口路径写成特殊格式,例如:/{{项目名称}}/xxxapi/v1这样在更改url重写规则时不会出现拦截其他项目中url。
但是这个方法不是最佳方案,还是改动了整个DMS的配置,建议使用下一种方案。
2. .Net core添加虚拟目录
2.1 配置swagger中间件
在startup.cs中添加如下代码,
// 1.生成json文件时,生成到虚拟目录下,VDir 来自配置app.UseSwagger(c =>{if (!string.IsNullOrEmpty(VDir)){// 设定模板:by webmote csdnc.RouteTemplate = $"/{VDir}/swagger/{{documentName}}/swagger.json";c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>{//api测试时增加虚拟目录 或完整路径也可以,完整路径已被webmote注释swaggerDoc.Servers = new List<OpenApiServer> { new OpenApiServer {Url = $"/{VDir}"// Url = $"{httpReq.Scheme}://{httpReq.Host.Value}/{virtualPath}"} };});}});// Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.app.UseSwaggerUI(c =>{if (!string.IsNullOrEmpty(VDir)){c.SwaggerEndpoint($"/{VDir}/swagger/v1/swagger.json", "App API V1");c.RoutePrefix = $"{VDir}/swagger";}else{c.SwaggerEndpoint("/swagger/v1/swagger.json", "App API V1");}});
2.2 配置appsettings.json
{"AppSettings": {"VirtualPath": "/虚拟目录"}}
2.3 对Api增加虚拟目录支持
这里引入了{dir}路由配置,把该类注入到服务中
public class MyTransformer : DynamicRouteValueTransformer{private string _route = string.Empty;public MyTransformer(string route){_route = route;}public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values){if (!values.ContainsKey("dir")) return new ValueTask<RouteValueDictionary>(values);var dir = (string)values["dir"];return new ValueTask<RouteValueDictionary>(values);}}
在UseEndpoints配置时,增加对二级目录的路由解释映射。
if (!string.IsNullOrEmpty(VDir)){services.AddSingleton<MyTransformer>(new MyTransformer(VDir));}
控制器WebApi的路由保持不变,不需要增加二级目录的
app.UseEndpoints(endpoints =>{endpoints.MapControllers();if (!string.IsNullOrEmpty(VirtualPath)){//这里是webmote定义的路由映射,可以方便的忽略二级目录endpoints.MapDynamicControllerRoute<MyTransformer>("{VirtualPath}/api/{controller}/{action}/{id?}");}});
[Route(“api/[controller]/[action]”)]
