How can you mount your app on a different base path?
For example, my controller's route is /api/keywords, but when running the web server I want the basepath to be /development, so my controller route would be /development/api/keywords. I would rather not have to modify my controllers. In old Web API versions you could mount an OWIN app in a different path so I'm looking to do something similar.
答案 0 :(得分:6)
有一种叫做UsePathBase的新方法可以轻松完成。 https://github.com/aspnet/HttpAbstractions/blob/bfa183747f6fb528087554c3d6ec58ef05f1c10a/src/Microsoft.AspNetCore.Http.Abstractions/Extensions/UsePathBaseExtensions.cs
答案 1 :(得分:0)
您可以查看原创精彩文章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);
}
}
并且ConfigureServices
班级中的Startup
方法变为
public void ConfigureServices(IServiceCollection services)
{
app.UseMiddleware<EnvironmentUrlRewritingMiddleware>();
services.AddMvc(options =>
{
options.UseEnvironmentPrefix(new RouteAttribute(_env.EnvironmentName));
});
}
唯一的缺点是它不会更改您的网址,因此如果您使用浏览器访问API,则不会看到包含您的环境的网址。 response.Redirect
始终发送GET请求,即使原始请求是POST。我没有找到最终的解决方案来反映URL的路径。
答案 2 :(得分:-1)
看看这个:
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() - 可用于配置Web和内容根。