1: public class Employee
3: public string Id { get; private set; }
4: public string Name { get; private set; }
5: public string Gender { get; private set; }
6: public DateTime BirthDate { get; private set; }
7: public string Department { get; private set; }
9: public Employee(string id, string name, string gender, DateTime birthDate, string department)
10: {
11: this.Id = id;
12: this.Name = name;
13: this.Gender = gender;
14: this.BirthDate = birthDate;
15: this.Department = department;
16: }
17: }
18: public class EmployeeRepository
19: {
20: private static IList<Employee> employees;
21: static EmployeeRepository()
22: {
23: employees = new List<Employee>();
24: employees.Add(new Employee(Guid.NewGuid().ToString(), "张三", "男",new DateTime(1981, 8, 24), "销售部"));
25: employees.Add(new Employee(Guid.NewGuid().ToString(), "李四", "女",new DateTime(1982, 7, 10), "人事部"));
26: employees.Add(new Employee(Guid.NewGuid().ToString(), "王五", "男",new DateTime(1981, 9, 21), "人事部"));
27: }
28: public IEnumerable<Employee> GetEmployees(string id = "")
29: {
30: return employees.Where(e => e.Id == id || string.IsNullOrEmpty(id) || id=="*");
31: }
32: }
对于如上图所示的两个页面实际上对应着同一个.aspx文件,即作为Web应用默认页面的Default.aspx。要通过一个独立于物理路径的URL来访问该.aspx页面,我们就需要采用URL路由机制来实现两者之间的映射。为此我们在添加的Global.asax文件中编写了如下几行代码。如下面的代码片断所示,在Application_Start方法中我们通过System.Web.Routing.RouteTable的Routes属性得到了表示路由对象列表的System.Web.Routing.RouteCollection对象,并调用该列表对象的MapPageRoute方法将Default.aspx页面(~/Default.aspx)与一个URL模板(employees/{name}/{id)进行了映射。
1: public class Global : System.Web.HttpApplication
3:
protected void Application_Start(object sender, EventArgs e)
5: var defaults = new RouteValueDictionary{{"name","*"},{"id","*"}};
6: RouteTable.Routes.MapPageRoute("", "employees/{name}/{id}", "~/Default.aspx", true,defaults);
作为MapPageRoute方法最后一个参数的RouteValueDictionary对象用于指定定义在路由模板中相应变量({name}和{id})的默认值。对于指定了默认值的路由对象,在当前请求地址的后续部分缺失的情况下,它会采用提供的默认值对该地址进行填充之后再进行模式的匹配。在如上所示的代码片断中,我们将{name}和{id}两变量的默认值均指定为“*”。对于针对URI为http://localhost:2738/employees的请求,我们注册的路由对象会将其格式成http://localhost:2738/employees/*/*,后者无疑是和定义的URL模式变现出来的模式是匹配的。
在Default.aspx页面中,我们分别采用GridView和DetailsView来显示所有员工列表和某个列表的详细信息,下面的代码片断表示该页面主体部分的HTML。值得一提的是:GridView模板中显示为员工姓名的HyperLinkField的连接采用了上面我们定义在URL模板(employees/{name}/{id))中的模式。
1: <form id="form1" runat="server">
2: <div id="page">
3: <asp:GridView ID="GridViewEmployees" runat="server" AutoGenerateColumns="false" Width="100%">
4: <Columns>
5: <asp:HyperLinkField HeaderText="姓名" DataTextField="Name" DataNavigateUrlFields="Name,Id" DataNavigateUrlFormatString="~/employees/{0}/{1}" />
6: <asp:BoundField DataField="Gender" HeaderText="性别" />
7: <asp:BoundField DataField="BirthDate" HeaderText="出生日期" DataFormatString="{0:dd/MM/yyyy}" />
8: <asp:BoundField DataField="Department" HeaderText="部门" />
9: </Columns>
10: </asp:GridView>
11: <asp:DetailsView ID="DetailsViewEmployee" runat="server" AutoGenerateRows="false" Width="100%">
12: <Fields>
13: <asp:BoundField DataField="ID" HeaderText= "ID" />
14: <asp:BoundField DataField="Name" HeaderText= "姓名" />
15: <asp:BoundField DataField="Gender" HeaderText="性别" />
16: <asp:BoundField DataField="BirthDate" HeaderText="出生日期" DataFormatString="{0:dd/MM/yyyy}" />
17: <asp:BoundField DataField="Department" HeaderText="部门" />
18: </Fields>
19: </asp:DetailsView>
20: </div>
21: </form>
Default.aspx页面的整个后台代码定义如下。由于所有员工列表和单一员工的详细信息均体现在该页面中,所以我们需要根据其请求地址来判断应该呈现怎样的数据,而这可以通过RouteData属性表示的路由数据来实现。Page具有一个类型为System.Web.Routing.RouteData的RouteData表示通过注册的与当前请求匹配的路由对象对请求地址进行解析生成的路由数据。RouteData的Values属性是一个存储路由变量的字典,其Key为变量名称。在如下所示的代码片断中,我们得到表示员工ID的路由变量(RouteData.Values["id"]),如果它是默认值则表示当前请求是针对员工列表的,反之则是这对指定的某个具体员工的。
1: public partial class Default : Page
3: private EmployeeRepository repository;
4: public EmployeeRepository Repository
6: get { return null == repository ? repository = new EmployeeRepository() : repository; }
8: protected void Page_Load(object sender, EventArgs e)
10: if (this.IsPostBack)
11: {
12: return;
13: }
14: string employeeId = this.RouteData.Values["id"] as string;
15: if (employeeId == "*" || string.IsNullOrEmpty(employeeId))
16: {
17: this.GridViewEmployees.DataSource = this.Repository.GetEmployees();
18: this.GridViewEmployees.DataBind();
19: this.DetailsViewEmployee.Visible = false;
20: }
21: else
22: {
23: var employees = this.Repository.GetEmployees(employeeId);
24: this.DetailsViewEmployee.DataSource = employees;
25: this.DetailsViewEmployee.DataBind();
26: this.GridViewEmployees.Visible = false;
27: }
28: }
29: }