2016-06-15 11 views
0

のために私はルートに特定のファイルが存在するときは常に特定のコントローラ/アクションメソッドへのすべての要求を私のASP.NET MVCのコアサイトをしたいと思います。アイデアは、私は特定の空のファイルを作成することにより、、必要に応じて「サイトメンテナンスのためダウン」のページを表示することができるということです。カスタムルータはメンテナンス

いくつかのカスタムミドルウェアを書きで遊んでたら、それは私がこれを行うカスタムIRouterを作成することができなければならないことを私に夜が明けました。特定のファイルが存在する場合は、すべてのルート要求を「保守」ルートにマップする必要があります。しかし、私はそれを働かせることはできません。ここで

は、カスタムルータの定義です:

public class OfflineRouteHandler : IRouter 
{ 
    private readonly string _path; 
    private readonly IPAddress _remote; 

    public OfflineRouteHandler(string offlinePath, string remoteIP) 
    { 
     _path = offlinePath; 
     _remote = IPAddress.Parse(remoteIP); 
    } 

    public VirtualPathData GetVirtualPath(VirtualPathContext context) 
    { 
     // this returns a value...but RouteAsync is never called 

     StringBuilder path = new StringBuilder(); 

     if(context.AmbientValues.ContainsKey("controller")) 
      path.Append(context.AmbientValues["controller"]); 

     if(context.AmbientValues.ContainsKey("action")) 
     { 
      if(path.Length > 0) path.Append("/"); 
      path.Append(context.AmbientValues["action"]); 
     } 

     return new VirtualPathData(this, "/" + path.ToString()); 
    } 

    public async Task RouteAsync(RouteContext context) 
    { 
     bool authorized = (context.HttpContext.Connection.RemoteIpAddress == _remote); 

     if(File.Exists(_path) && authorized) 
     { 
      // just for testing... but the method never gets called 
      var i = 9; 
      i++; 
     } 

     context.IsHandled = true; 
    } 
} 

次のように私はStartup.csでConfigure()でそれを呼び出す:

string offlinePath = Path.Combine(Directory.GetParent(env.WebRootPath).FullName, "offline.txt"); 

app.UseMvc(routes => 
{ 
    routes.Routes.Add(new TemplateRoute(new OfflineRouteHandler(offlinePath, "50.3.3.2"), "home/offline", new DefaultInlineConstraintResolver(routeOptions))); 

    routes.MapRoute(
     name: "default", 
     template: "{controller=Home}/{action=Index}/{id?}"); 
}); 

routeOptionsConfigure();

への呼び出しに渡されますどんな助けでも大歓迎です!

+1

タイトルにタグを入れないで、適切なタグを使用してください! – Tseng

答えて

1

これはテストされていないですが、私は、ミドルウェアのアプローチのために行ってきました。

これは、context.Request.Pathをパスで変更する点で、UseStatusCodePagesWithReExecute関数と同様の方法を使用します。私はOptions patternを使用してOfflineMiddlewareの設定をロードしました。

ファイルが存在する場合は基本的に、ミドルウェアは、あなたが「ホーム/オフライン」先のパスへのパスを変更して、MVCパイプラインを実行を続けます。

ミドルウェアの前にUseStaticFiles()を追加したので、オフラインページの静的ファイルがすべて提供されます。MVCパイプラインに送信されるリクエストのみがインターセプトされ、これらのリクエストはすべてホーム/オフラインになります。

public class Startup 
{ 
    //Partial Starup class 
    public void ConfigureServices(IServiceCollection services) 
    { 
    services.Configure<OfflineMiddlewareSettings>(settings => 
    { 
     settings.OfflinePath = "thePath"; 
     settings.RemoteIP = "50.3.3.2"; 
    }); 

    // Add framework services. 
    services.AddMvc(); 
    } 

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptionsMonitor<MyValues> monitor) 
    { 
    loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
    loggerFactory.AddDebug(); 

    app. UseStaticFiles(); 

    app.UseMiddleware<OfflineMiddleware>(); 
    app.UseMvc(); 
    } 

} 

public class OfflineMiddleware 
{ 
    private readonly RequestDelegate _next; 
    private readonly string _path; 
    private readonly IPAddress _remote; 

    public OfflineMiddleware(RequestDelegate next, IOptions<OfflineMiddlewareSettings> settings) 
    { 
     _next = next; 
     _path = settings.Value.OfflinePath; 
     _remote = IPAddress.Parse(settings.Value.OfflinePath); 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     bool authorized = (context.Connection.RemoteIpAddress == _remote); 

     if (File.Exists(_path) && authorized) 
     { 
      context.Request.Path = "home/offline"; 
     } 

     await _next.Invoke(context); 
    } 
} 

public class OfflineMiddlewareSettings 
{ 
    public string OfflinePath { get; set; } 
    public string RemoteIP { get; set; } 
} 
+0

魅力的な作品です! 〜また、ConfigureServicesに設定情報を保存することについてのインラインヒントについては、tooxもあります。私がこれまでやっていたやり方は、あなたのものよりずっと面倒です。 –

関連する問題