一、异常描述
.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 csdn
c.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]”)]