如何將您的應用安裝在不同的基本路徑上?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的路徑。