您可以查看原创精彩文章here
首先创建一个继承自IApplicationModelConvention接口的类
public class EnvironmentRouteConvention : IApplicationModelConvention
{
private readonly AttributeRouteModel _centralPrefix;
public EnvironmentRouteConvention(IRouteTemplateProvider routeTemplateProvider)
{
_centralPrefix = new AttributeRouteModel(routeTemplateProvider);
}
public void Apply(ApplicationModel application)
{
foreach (var controller in application.Controllers)
{
var matchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel != null).ToList();
if (matchedSelectors.Any())
{
foreach (var selectorModel in matchedSelectors)
{
//This will apply only to your API controllers. You may change that depending of your needs
if (selectorModel.AttributeRouteModel.Template.StartsWith("api"))
{
selectorModel.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_centralPrefix, selectorModel.AttributeRouteModel);
}
}
}
}
}
然后创建一个类只是为了更容易和更清洁的使用。
public static class MvcOptionsExtensions
{
public static void UseEnvironmentPrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute)
{
opts.Conventions.Insert(0, new EnvironmentRouteConvention(routeAttribute));
}
}
现在要使用它,首先非常常用,将您的环境保存在 Startup 类的属性中
private IHostingEnvironment _env;
public Startup(IHostingEnvironment env)
{
_env = env;
}
然后你需要做的就是调用你的静态扩展类
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.UseEnvironmentPrefix(new RouteAttribute(_env.EnvironmentName));
});
}
但还有最后一件事需要关心。无论您有什么客户端使用您的 API,您当然不想更改您发送的 HTTP 请求的所有 URL。所以诀窍是创建一个中间件,它将修改您请求的Path 以包含您的环境名称。 (source)
public class EnvironmentUrlRewritingMiddleware
{
private readonly RequestDelegate _next;
public EnvironmentUrlRewritingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, IHostingEnvironment env)
{
var path = context.Request.Path.ToUriComponent();
//Again this depends of your need, whether to activate this to your API controllers only or not
if (!path.StartsWith("/" + env.EnvironmentName) && path.StartsWith("/api"))
{
var newPath = context.Request.Path.ToString().Insert(0, "/" + env.EnvironmentName);
context.Request.Path = newPath;
}
await _next.Invoke(context);
}
}
您的Startup 类中的ConfigureServices 方法变为
public void ConfigureServices(IServiceCollection services)
{
app.UseMiddleware<EnvironmentUrlRewritingMiddleware>();
services.AddMvc(options =>
{
options.UseEnvironmentPrefix(new RouteAttribute(_env.EnvironmentName));
});
}
唯一的缺点是它不会更改您的 URL,因此如果您使用浏览器访问 API,您将看不到包含您的环境的 URL。 response.Redirect 始终发送 GET 请求,即使原始请求是 POST 也是如此。我还没有找到反映 URL 路径的最终解决方案。