我也不知道如何使用路由完成。但實現此目的的一種方法是使用URL重寫。整個過程有幾個步驟,製作起來相當簡單。
你加在Global.asax
下面的函數。
void Application_BeginRequest(object sender, EventArgs e)
{
//Here you will get exception 'Index was outside the bounds of the array' when loading home page, handle accordingly
string currentsegment = Request.Url.Segments[1];
string RewritePath = "";
if (IsTeam(currentsegment))
{
RewritePath = "~/team.aspx?team=" + currentsegment;
}
if (IsPlayer(currentsegment))
{
RewritePath = "~/player.aspx?player=" + currentsegment;
}
if (RewritePath != "") {
// Adding all query string items to the new URL
for (int I = 0; I <= Request.QueryString.Count - 1; I++)
{
RewritePath = RewritePath + "&" + Request.QueryString.Keys[I] + "=" + Request.QueryString[I];
}
Context.RewritePath(RewritePath);
}
}
因此,如果URL已經是/some-title-here
可以使用Request.Url.Segments
陣列得到some-title-here
部分。
然後根據你的代碼檢測這個標題是團隊還是玩家。在任何情況下,您都可以通過調用Context.RewritePath(...)
來更改內部URL。
一個重要的事情是,您需要手動添加所有查詢字符串項目,以便將它們傳遞到您的頁面。
此外,在您的代碼Request.Url
將知道重寫的URL,而不是原來的。
快速測試它的方法是實現IsTeam(...)
和IsPlayer(...)
函數如下。只有當這個代碼打到/player-tasos~/player.aspx?player=player-tasos
頁面加載和當擊中/team-stackoverflow頁面加載頁面。
private bool IsTeam(string segment)
{
return segment.StartsWith("team");
}
private bool IsPlayer(string segment)
{
return segment.StartsWith("player");
}
到目前爲止,這種方法的工作原理,但它有一個主要問題。當有一個回髮網址更改爲您在Context.RewritePath(...)
爲了避免這個問題,你需要添加到您的二期項目ASP.NET文件夾
- App_Browsers文件
- App_Code文件
在App_Code文件夾中創建文件FormRewriter.cs
並添加以下代碼(在我的演示根命名空間是WebFormsRewriting
)
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.UI;
namespace WebFormsRewriting
{
public class FormRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
base.Render(new RewriteFormHtmlTextWriter(writer));
}
}
public class RewriteFormHtmlTextWriter : System.Web.UI.HtmlTextWriter
{
public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
: base(writer)
{
this.InnerWriter = writer.InnerWriter;
}
public RewriteFormHtmlTextWriter(System.IO.TextWriter writer)
: base(writer)
{
base.InnerWriter = writer;
}
public override void WriteAttribute(string name, string value, bool fEncode)
{
// If the attribute we are writing is the "action" attribute, and we are not on a sub-control,
// then replace the value to write with the raw URL of the request - which ensures that we'll
// preserve the PathInfo value on postback scenarios
if ((name == "action"))
{
HttpContext Context = default(HttpContext);
Context = HttpContext.Current;
if (Context.Items["ActionAlreadyWritten"] == null)
{
// Because we are using the UrlRewriting.net HttpModule, we will use the
// Request.RawUrl property within ASP.NET to retrieve the origional URL
// before it was re-written. You'll want to change the line of code below
// if you use a different URL rewriting implementation.
value = Context.Request.RawUrl;
// Indicate that we've already rewritten the <form>'s action attribute to prevent
// us from rewriting a sub-control under the <form> control
Context.Items["ActionAlreadyWritten"] = true;
}
}
base.WriteAttribute(name, value, fEncode);
}
}
}
在App_Browsers文件夾中創建文件Form.browser
,並添加以下代碼片段。請注意,將Adapter的類名稱與其名稱空間放在一起。
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.HtmlControls.HtmlForm"
adapterType="WebFormsRewriting.FormRewriterControlAdapter" />
</controlAdapters>
</browser>
</browsers>
就是這樣。添加這兩個文件將處理PostBack問題。如果您將FormRewriter.cs
放在App_Code
文件夾之外,它將不起作用。此外,這兩個文件夾必須上傳到生產服務器。
我已經在.NET 3.5和.NET 4.0中使用了這種方法多年,沒有任何問題。今天,我也在.NET 4.5 Web Forms項目中測試了它,它沒有問題。
以上所有的都是基於ScottGu的article對上述
路由如何知道'foo'是'mysite.com/foo'中的團隊還是玩家?在您鏈接到的頁面上,除了其他內容外,還說「{language} {country}/{action}」無效,因爲路由無法知道語言的結束位置和國家的起始位置。你的想法有同樣的問題。 – user1429080 2014-10-01 19:48:57
這不可能使用System.Web.Routing - URL的結構看起來與路由引擎完全相同,那麼它將如何知道URL引用的實體類型?爲什麼不能使用* mysite.com/teams/{teamname} *和* mysite.com/players/{playername} *代替? – sh1rts 2014-10-02 01:44:47
感謝您的意見。我希望能夠爲團隊和玩家提供相同的簡單網址結構,以保持簡潔。 我想這可能是可能實現,也許坐在路由引擎的前面,這樣我自己的HTTP模塊: 用戶導航到:mysite.com/JoeBloggs, 我的HTTP模塊,然後做一個數據庫查詢和然後某種server.transfer:mysite.com/players/JoeBloggs, URL路由然後相應地處理mysite.com/players/{playername}路線。 但是,這聽起來過於複雜這個問題? – DavidReid 2014-10-02 13:26:51