如何将您的应用安装在不同的基本路径上?Kestrel和ASP.NET Core MVC使用自定义基本路径
例如,我的控制器的路由是/ api/keywords,但是当运行web服务器时我希望basepath是/ development,所以我的控制器路由是/ development/api/keywords。我宁愿不必修改我的控制器。在旧的Web API版本中,您可以在不同的路径中安装OWIN应用程序,所以我期望做类似的事情。
如何将您的应用安装在不同的基本路径上?Kestrel和ASP.NET Core MVC使用自定义基本路径
例如,我的控制器的路由是/ api/keywords,但是当运行web服务器时我希望basepath是/ development,所以我的控制器路由是/ development/api/keywords。我宁愿不必修改我的控制器。在旧的Web API版本中,您可以在不同的路径中安装OWIN应用程序,所以我期望做类似的事情。
在此请看:
public class Program
{
public static void Main(string[] args)
{
var contentRoot = Directory.GetCurrentDirectory();
var config = new ConfigurationBuilder()
.SetBasePath(contentRoot)
.Build();
var hostBuilder = new WebHostBuilder()
//Server
.UseKestrel()
//Content root - in this example it will be our current directory
.UseContentRoot(contentRoot)
//Web root - by the default it's wwwroot but here is the place where you can change it
.UseWebRoot("wwwroot")
//Startup
.UseStartup<Startup>();
var host = hostBuilder.Build();
host.Run();
}
}
有两种扩展方法 - UseWebRoot()和UseContentRoot() - 可用于配置网络和内容的根。
您可以查看原始大文章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));
}
}
我们使用它,第一个很常见的,节省您的环境中您的启动类的属性
private IHostingEnvironment _env;
public Startup(IHostingEnvironment env)
{
_env = env;
}
然后所有你需要做的就是打电话给你的静态extention类
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));
});
}
唯一的缺点是它不会改变你的网址,因此,如果你打你的API与您的浏览器,您将不会看到包含您的环境的网址。 response.Redirect
总是发送GET请求,即使原始请求是POST。我还没有找到最终的解决方案来反映URL的路径。