Asp.net-Web-Api

Kestrel 和 ASP.NET Core MVC 使用自定義基本路徑

  • August 16, 2018

如何將您的應用程序安裝在不同的基本路徑上?

例如,我的控制器的路由是 /api/keywords,但是在執行 Web 伺服器時,我希望基本路徑是 /development,所以我的控制器路由是 /development/api/keywords。我寧願不必修改我的控制器。在舊的 Web API 版本中,您可以在不同的路徑中安裝 OWIN 應用程序,所以我正在尋找類似的東西。

有一種名為 UsePathBase 的新方法可以輕鬆完成此操作。 https://github.com/aspnet/HttpAbstractions/blob/bfa183747f6fb528087554c3d6ec58ef05f1c10a/src/Microsoft.AspNetCore.Http.Abstractions/Extensions/UsePathBaseExtensions.cs

您可以在此處查看原始的精彩文章

首先創建一個繼承自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您的請求以包含您的環境名稱。(來源

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);
   }
}

ConfigureServicesStartup課堂上的方法變成了

public void ConfigureServices(IServiceCollection services)
{
   app.UseMiddleware<EnvironmentUrlRewritingMiddleware>();
   services.AddMvc(options =>
   {
       options.UseEnvironmentPrefix(new RouteAttribute(_env.EnvironmentName));
   });
}

唯一的缺點是它不會更改您的 URL,因此如果您使用瀏覽器訪問 API,您將看不到包含您的環境的 URL。response.Redirect即使原始請求是 POST,也始終發送 GET 請求。我還沒有找到反映 URL 路徑的最終解決方案。

引用自:https://stackoverflow.com/questions/40163708