有人能提供一些示例来实现这一点吗?
此外,有没有使用这种路由风格的“最佳实践”?
更新:这已经发布在codeplex上了。完整的源代码以及预先编译的程序集都可以下载。我还没有时间在网站上发布文档,所以现在只能用这篇SO帖子代替。
更新:我添加了一些新特性来处理1)路由排序、2)路由参数约束和3)路由参数默认值。下面的文本反映了此更新。
实际上,我为我的MVC项目做过类似的事情(我不知道Jeff在stackoverflow上是如何做到的)。我定义了一组自定义属性:UrlRoute、UrlRouteParameterConstraint、UrlRouteParameterDefault。它们可以附加到MVC控制器操作方法上,以便自动绑定路由、约束和默认值。
示例用法:
(请注意,此示例有些牵强,但它演示了该功能)
public class UsersController : Controller
{
// Simple path.
// Note you can have multiple UrlRoute attributes affixed to same method.
[UrlRoute(Path = "users")]
public ActionResult Index()
{
return View();
}
// Path with parameter plus constraint on parameter.
// You can have multiple constraints.
[UrlRoute(Path = "users/{userId}")]
[UrlRouteParameterConstraint(Name = "userId", Regex = @"\d+")]
public ActionResult UserProfile(int userId)
{
// ...code omitted
return View();
}
// Path with Order specified, to ensure it is added before the previous
// route. Without this, the "users/admin" URL may match the previous
// route before this route is even evaluated.
[UrlRoute(Path = "users/admin", Order = -10)]
public ActionResult AdminProfile()
{
// ...code omitted
return View();
}
// Path with multiple parameters and default value for the last
// parameter if its not specified.
[UrlRoute(Path = "users/{userId}/posts/{dateRange}")]
[UrlRouteParameterConstraint(Name = "userId", Regex = @"\d+")]
[UrlRouteParameterDefault(Name = "dateRange", Value = "all")]
public ActionResult UserPostsByTag(int userId, string dateRange)
{
// ...code omitted
return View();
}
UrlRouteAttribute的定义:
/// <summary>
/// Assigns a URL route to an MVC Controller class method.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class UrlRouteAttribute : Attribute
{
/// <summary>
/// Optional name of the route. If not specified, the route name will
/// be set to [controller name].[action name].
/// </summary>
public string Name { get; set; }
/// <summary>
/// Path of the URL route. This is relative to the root of the web site.
/// Do not append a "/" prefix. Specify empty string for the root page.
/// </summary>
public string Path { get; set; }
/// <summary>
/// Optional order in which to add the route (default is 0). Routes
/// with lower order values will be added before those with higher.
/// Routes that have the same order value will be added in undefined
/// order with respect to each other.
/// </summary>
public int Order { get; set; }
}
UrlRouteParameterConstraintAttribute的定义:
/// <summary>
/// Assigns a constraint to a route parameter in a UrlRouteAttribute.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class UrlRouteParameterConstraintAttribute : Attribute
{
/// <summary>
/// Name of the route parameter on which to apply the constraint.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Regular expression constraint to test on the route parameter value
/// in the URL.
/// </summary>
public string Regex { get; set; }
}
UrlRouteParameterDefaultAttribute的定义:
/// <summary>
/// Assigns a default value to a route parameter in a UrlRouteAttribute
/// if not specified in the URL.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class UrlRouteParameterDefaultAttribute : Attribute
{
/// <summary>
/// Name of the route parameter for which to supply the default value.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Default value to set on the route parameter if not specified in the URL.
/// </summary>
public object Value { get; set; }
}
修改Global.asax.cs:
将对MapRoute的调用替换为对RouteUtility.RegisterUrlRoutesFromAttributes函数的单个调用:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteUtility.RegisterUrlRoutesFromAttributes(routes);
}
RouteUtility.RegisterUrlRoutesFromAttributes的定义:
完整源代码可在codeplex上找到。如果您有任何反馈或错误报告,请访问该网站。
你还可以尝试使用AttributeRouting,可以通过github或者nuget获得。
我是这个项目的作者,这也是一种无耻的自夸。但是我真的很喜欢它,你也可能会喜欢。GitHub仓库wiki中有大量文档和示例代码。
使用这个库,你可以做很多事情:
我确定还有其他东西我忘了提到。检查一下吧,通过nuget安装非常简便。
注意:截至2012年4月16日,AttributeRouting也支持新的Web API基础架构。 如果你正在寻找可以处理它的东西,只是为了确保。感谢subkamran!
1. 下载RiaLibrary.Web.dll并将其引用到您的ASP.NET MVC网站项目中
2. 使用[Url]属性装饰控制器方法:
public SiteController : Controller
{
[Url("")]
public ActionResult Home()
{
return View();
}
[Url("about")]
public ActionResult AboutUs()
{
return View();
}
[Url("store/{?category}")]
public ActionResult Products(string category = null)
{
return View();
}
}
顺便提一下,在'{?category}'参数中的'?'符号表示它是可选的。在路由默认值中,您不需要明确指定这一点,因为它等同于以下内容:
routes.MapRoute("Store", "store/{category}",
new { controller = "Store", action = "Home", category = UrlParameter.Optional });
3. 更新 Global.asax.cs 文件
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoutes(); // This does the trick
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
public SiteController : Controller
{
[Url("admin/articles/edit/{id}", Constraints = @"id=\d+")]
public ActionResult ArticlesEdit(int id)
{
return View();
}
[Url("articles/{category}/{date}_{title}", Constraints =
"date=(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")]
public ActionResult Article(string category, DateTime date, string title)
{
return View();
}
}
[Url("forums/{?category}", Order = 2)]
public ActionResult Threads(string category)
{
return View();
}
[Url("forums/new", Order = 1)]
public ActionResult NewThread()
{
return View();
}
{?param}
这种可选参数的命名方式。 - Jarrod Dixon这篇文章是为了补充DSO的回答。
当我将我的路由转换成属性时,我需要处理ActionName属性。因此在GetRouteParamsFromAttribute中:
ActionNameAttribute anAttr = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), false)
.Cast<ActionNameAttribute>()
.SingleOrDefault();
// Add to list of routes.
routeParams.Add(new MapRouteParams()
{
RouteName = routeAttrib.Name,
Path = routeAttrib.Path,
ControllerName = controllerName,
ActionName = (anAttr != null ? anAttr.Name : methodInfo.Name),
Order = routeAttrib.Order,
Constraints = GetConstraints(methodInfo),
Defaults = GetDefaults(methodInfo),
});
我发现路由的命名不太合适。名称是通过controllerName.RouteName动态构建的。但我的路由名称是控制器类中的const字符串,我还使用这些const来调用Url.RouteUrl。因此,我真的需要属性中的路由名称是实际路由的名称。
另一件事情是将默认值和约束属性转换为AttributeTargets.Parameter,以便我可以将它们粘贴到params上。
我需要在使用AsyncController的asp.net mvc 2中使ITCloud路由工作 - 为此,只需编辑源代码中的RouteUtility.cs类并重新编译即可。您必须从第98行的操作名称中去掉“Completed”
// Add to list of routes.
routeParams.Add(new MapRouteParams()
{
RouteName = String.IsNullOrEmpty(routeAttrib.Name) ? null : routeAttrib.Name,
Path = routeAttrib.Path,
ControllerName = controllerName,
ActionName = methodInfo.Name.Replace("Completed", ""),
Order = routeAttrib.Order,
Constraints = GetConstraints(methodInfo),
Defaults = GetDefaults(methodInfo),
ControllerNamespace = controllerClass.Namespace,
});
UrlRoute
和 UrlRouteParameterDefault
属性装饰 XXXXCompleted ActionResult:[UrlRoute(Path = "ActionName/{title}")]
[UrlRouteParameterDefault(Name = "title", Value = "latest-post")]
public ActionResult ActionNameCompleted(string title)
{
...
}
http://github.com/djMax/AlienForce/tree/master/Utilities/Web/