使用 MVC 和 ASP.Net Core 重寫動態 url
我正在使用 ASP.Net Core 和 MVC 6 重寫我的 FragSwapper.com 網站(目前在 Asp 2.0 中!),我正在嘗試做一些我通常必須打破 URL Re-Write 工具和數據庫程式碼的事情和一些重定向,但我想知道在 ASP.Net Core 中是否有“更好”的方法可以使用 MVC 路由和重定向。
這是我的場景…
- URL 訪問網站:$$ root $$
*怎麼辦:*去往常
$$ Home $$控制器和$$ Index $$查看(無$$ ID $$)。…它現在這樣做:
app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
- URL 訪問網站:$$ root $$/ControllerName/…亞達亞達…
*怎麼做:*去控制器,等等……這一切也都有效。
- 棘手的一個: URL 訪問站點:$$ root $$/一些字元串
**怎麼辦:**訪問數據庫並執行一些邏輯來決定是否找到事件 ID。如果我這樣做,我會去
$$ Event $$控制器和$$ Index $$查看和$$ ID $$我發現的任何東西。如果不是,我嘗試查找主機 ID 並轉到$$ Home $$控制器和$$ Organization $$用那個查看$$ ID $$我發現。如果我沒有找到和事件或主持人去往常$$ Home $$控制器和$$ Index $$查看(無$$ ID $$).
這裡最大的問題是我想重定向到 2 個不同控制器中的三個完全不同的視圖之一。
所以底線是當使用者來到我的站點的根目錄並且上面有一個“/Something”並且該邏輯是數據庫驅動的時,我想做一些邏輯。
如果您理解這個問題,您現在可以停止閱讀……如果您覺得有必要了解為什麼需要所有這些邏輯,您可以繼續閱讀以獲得更詳細的上下文。
我的網站基本上有兩種模式:查看活動和不查看活動!通常一次執行 4 或 5 個事件,但大多數使用者只對一個事件感興趣,但它每 4 個月左右發生一次不同的事件..我有一個
$$ Host $$實體,每個主持人每年最多舉辦 4 場活動,一次一個。大多數使用者只關心一個主機的事件。 我試圖避免讓使用者總是去事件地圖並找到事件並點擊它,因為我可以顯示地圖的次數有限制(免費),這真的沒有必要。99.99% 的使用者在我的網站上的時間是在事件螢幕上,而不是在我的主螢幕上,並且一次只對一個事件感興趣。將來我想對其進行編碼,這樣如果他們訪問我的網站,他們就會直接參加他們的活動或來自他們最喜歡的主持人的新活動,這樣我就可以避免大量點擊並專注於我的
$$ Home $$新手的控制器頁面……但我還沒有自動登錄工作,所以這是次要的。 但現在我希望主持人始終擁有相同的活動網址:FragSwapper.com/
$$ Host Abbreviation $$…並且知道它總是會出現在他們目前的事件中,每 4 個月有一個不同的 ID !!! 瘋了…我知道…但從技術上講很容易做到,我只是不知道如何在 MVC 中正確地做到這一點。
更新:ASP.Net Core 1.1
根據發行說明
RewriteMiddleware,已經創建了一個新的。這提供了幾種不同的預定義重寫選項和實用程序擴展方法,最終可能會修改請求路徑,就像在此答案中所做的那樣。參見例如實現
RewriteRule具體到 OP 問題,您需要實現自己的
IRule類(從頭開始或擴展現有的類RewriteRule,例如 ,它基於正則表達式)。你可能會用一個新的AddMyRule()擴展方法來補充它RewriteOptions。您可以創建自己的中間件並將其添加到 MVC 路由之前的請求管道中。
這允許您在評估 MVC 路由之前將程式碼注入管道。這樣,您將能夠:
- 檢查傳入請求中的路徑
- 在數據庫中搜尋具有相同值的 eventId 或 hostId
- 如果找到事件或主機,則將傳入請求路徑更新為
Event/Index/{eventId}或Home/Organization/{hostId}- 讓下一個中間件(MVC 路由)處理請求。他們會看到之前的中間件對請求路徑所做的任何更改
例如,創建您自己的
EventIdUrlRewritingMiddleware中間件,該中間件將嘗試將傳入請求路徑與數據庫中的 eventId 進行匹配。如果匹配,它將原始請求路徑更改為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在地址欄中。(即使在內部更新了原始路徑)