我也不知道如何使用路由完成。但实现此目的的一种方法是使用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