9

我正在重寫我的FragSwapper.com網站(目前在Asp 2.0!)與ASP.Net核心和MVC 6,我試圖做一些我通常會有打破URL重寫工具以及數據庫代碼和一些重定向,但我想知道是否有一種「更好」的方式在ASP.Net Core中使用MVC路由和重定向。動態網址重寫與MVC和ASP.Net核心

這裏是我的情況...

  • 網址訪問網站:[根]

    怎麼辦:轉到平時[首頁]控制器和[索引]視圖(無[ID])。 ......現在做這個的:

    app.UseMvc(routes => 
    { 
        routes.MapRoute(
        name: "default", 
        template: "{controller=Home}/{action=Index}/{id?}"); 
    }); 
    
  • 網址訪問網站:[根]/ControllerName/...內容十分重要...

    怎麼辦:圍棋到控制器等...所有這一切都起作用。

  • 棘手的一個:URL訪問網站:[根]/SomeString

    怎麼辦:訪問數據庫,並做一些邏輯來決定,如果我找到一個事件ID。如果我這樣做,我去[事件]控制器和[索引]視圖和我發現的任何[ID]。如果沒有,我嘗試找到一個主機ID,然後轉到[Home] Controller和[Organization] View with THAT [ID]找到。如果我沒有找到並且Event或Host轉到通常的[Home]控制器和[Index]視圖(無[ID])。

這裏的大問題是,我想重定向到兩個不同控制器中的三個完全不同的視圖之一。

所以底線是我想做一些邏輯,當用戶來到我的網站的根目錄,並有一個單一的「/東西」,並且該邏輯是數據庫驅動。

如果你明白這個問題,你可以立即停止閱讀......如果你覺得有必要理解爲什麼需要所有這些邏輯,你可以閱讀更詳細的上下文。

我的網站基本上有兩種模式:查看活動和不查看 活動!通常一次運行4或5個事件,但 大多數用戶只對一個事件感興趣,但每隔4個月左右就會發生一次不同的事件 ..我有一個[Host]實體,每個主機最多可容納 4一年一次的活動。大多數用戶只關心一個主機的 事件。

我試圖避免使用戶隨時到事件地圖,找到 事件,並點擊它,因爲我有一個限制,我可以有多少次 顯示在地圖(免費),這真的不必要。用戶在我的網站上的時間爲99.99%,他們在事件屏幕上,而不是我的主頁 屏幕,並且一次只對一個事件感興趣。在 未來,我想編碼它,所以如果他們來到我的網站,他們去 他們的事件或從他們最喜愛的主機的新事件,所以我可以避免 點擊很多,並集中我的[首頁]控制器頁面的newbs ...但我 還沒有自動登錄工作,所以這是背後的燃燒器。

但現在我要主機總是爲他們的活動一樣網址: FragSwapper.com/[Host縮寫] ...並知道它會永遠去後者具有不同ID 他們目前的情況下,每4個月!

瘋狂......我知道......但技術上很容易做到,我只是不知道 如何在MVC中正確地做到這一點,以及如何完成任務。

回答

14

更新:ASP.Net 1.1核心

按照release notes,新RewriteMiddleware已創建。

這提供了幾個不同的預定義重寫選項和實用程序擴展方法,最終可能會修改請求路徑,因爲它已在此答案中完成。見例如RewriteRule

實施具體到OP問題,你需要實現自己的IRule類(從頭開始或擴大現有的像RewriteRule,這是基於正則表達式)。您可能需要使用的AddMyRule()擴展方法對其進行補充。


您可以創建自己的middleware,它的MVC路由之前添加到請求管道。

這允許您在評估MVC路由之前將代碼注入到管道中。這樣,您將能夠:

  1. 檢查在傳入請求的路徑
  2. 搜索數據庫中的一個事件ID或主機ID使用相同的值
  3. 如果發現事件或主機,更新傳入請求路徑爲Event/Index/{eventId}Home/Organization/{hostId}
  4. 讓下一個中間件(MVC路由)負責處理請求。他們會看到由以前的中間件

例如,create your ownEventIdUrlRewritingMiddleware中間件將嘗試傳入請求路徑對數據庫中的事件ID匹配的請求路徑中的任何改變。如果匹配,將原始請求路徑更改爲Event/Index/{eventId}

public class EventIdUrlRewritingMiddleware 
{ 
    private readonly RequestDelegate _next;   

    //Your constructor will have the dependencies needed for database access 
    public EventIdUrlRewritingMiddleware(RequestDelegate next) 
    { 
     _next = next; 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     var path = context.Request.Path.ToUriComponent(); 

     if (PathIsEventId(path)) 
     { 
      //If is an eventId, change the request path to be "Event/Index/{path}" so it is handled by the event controller, index action 
      context.Request.Path = "/Event/Index" + path; 
     } 

     //Let the next middleware (MVC routing) handle the request 
     //In case the path was updated, the MVC routing will see the updated path 
     await _next.Invoke(context); 

    } 

    private bool PathIsEventId(string path) 
    {    
     //The real midleware will try to find an event in the database that matches the current path 
     //In this example I am just using some hardcoded string 
     if (path == "/someEventId") 
     { 
      return true; 
     } 

     return false; 
    } 
} 

然後創建另一個類HostIdUrlRewritingMiddleware按照相同的方法。

最後添加新的中間件在Startup.Configure方法管道,確保他們的路由和MVC中間件之前加入:

 app.UseMiddleware<EventIdUrlRewritingMiddleware>(); 
     app.UseMiddleware<HostIdUrlRewritingMiddleware>(); 
     app.UseMvc(routes => 
     { 
      routes.MapRoute(
       name: "default", 
       template: "{controller=Home}/{action=Index}/{id?}"); 
     }); 

利用這種配置:

  • /轉到HomeController.Index動作
  • /Home/About轉到HomeController.About動作
  • /Event/Index/1轉到EventController.Index動作ID = 1
  • /someEventId轉到EventController.Index行動,ID = someEventId

請注意有沒有HTTP重定向參與。在瀏覽器中打開/someEventId時,只有一個http請求,瀏覽器將在地址欄中顯示/someEventId。 (即使內部原始路徑已更新)

+0

那麼這肯定比我預期的答案要多,而且這個概念當然是我需要的!我覺得必須有一些方法可以介入,我只是不知道在哪裏尋找。我仍然在玩它,但我毫不懷疑中間件(對我來說這是一個完全未知的概念)是我需要做的。我發現使用.Net Core的最大問題是,足夠的人還沒有像我一樣的問題,它讓我很少看到地方。非常感謝您的寶貴時間。 –

+0

完全沒問題!關於這個框架,我完全同意你的看法,許多事情在asp.net核心中已經發生了變化,有時很難找到解決的辦法。如果有疑問,我嘗試從[docs](https://docs.asp.net/en/latest/)開始,但即使在那裏您也可以找到許多尚未涉及的主題。 –

+0

您是在MVC之前還是之後添加了中間件?然後在調用next之前更改路徑?你設置了什麼路徑以及應該處理它的控制器和路由是什麼?很難知道沒有看到你的代碼,但上面的答案在新的1.0.1應用程序中正常工作。也許嘗試一個新的空應用程序,並慢慢開始添加你的代碼,如果你仍然有問題,它可能是值得開一個新的問題! (你可能也會發現這篇文章對我有用[這篇文章](http://www.dotnetcurry.com/aspnet/1312/aspnet-core-request-pipeline-vanity-url),它擴展了同樣的想法) –