访问通过查询字符串传递的路由值参数的一致方式
Consistent way to access route value parameters passed through querystring
我在 global.asax
中定义了以下路线
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Portal", action = "Index", id = UrlParameter.Optional }
);
我无法控制用户是否访问带有“/useraccount/edit/1”或“/useraccount/edit?id=1”的页面。使用 UrlHelper Action 方法生成 url 时,如果将 id 作为查询字符串参数传递,则 id 值不包含在 RouteData 中。
new UrlHelper(helper.ViewContext.RequestContext).Action(
action, helper.ViewContext.RouteData.Values)
我正在寻找一种访问 id 值的一致方法,无论使用哪个 url 访问页面,或者一种自定义 RouteData 对象初始化的方法,以便它检查缺少路由参数的查询字符串,如果找到则添加它们。
您可以使用
@Url.RouteUrl("Default", new { id = ViewContext.RouteData.Values["id"] != null ? ViewContext.RouteData.Values["id"] : Request.QueryString["id"] })
试试这个解决方案
var qs = helper.ViewContext
.HttpContext.Request.QueryString
.ToPairs()
.Union(helper.ViewContext.RouteData.Values)
.ToDictionary(x => x.Key, x => x.Value);
var rvd = new RouteValueDictionary(qs);
return new UrlHelper( helper.ViewContext.RequestContext).Action(action, rvd);
转换 NameValueCollection 试试这个
public static IEnumerable<KeyValuePair<string, object>> ToPairs(this NameValueCollection collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
return collection.Cast<string>().Select(key => new KeyValuePair<string, object>(key, collection[key]));
}
Extending Route 最终成为满足我需求的最简单的解决方案;感谢你的建议!让我知道我的解决方案是否有任何明显的问题(class 名称除外)。
FrameworkRoute.cs
public class FrameworkRoute: Route
{
public FrameworkRoute(string url, object defaults) :
base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
{
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
if (routeData != null)
{
foreach (var item in routeData.Values.Where(rv => rv.Value == UrlParameter.Optional).ToList())
{
var val = httpContext.Request.QueryString[item.Key];
if (!string.IsNullOrWhiteSpace(val))
{
routeData.Values[item.Key] = val;
}
}
}
return routeData;
}
}
Global.asax.cs
protected override void Application_Start()
{
// register route
routes.Add(new FrameworkRoute("{controller}/{action}/{id}", new { controller = "Portal", action = "Index", id = UrlParameter.Optional }));
我在 global.asax
中定义了以下路线routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Portal", action = "Index", id = UrlParameter.Optional }
);
我无法控制用户是否访问带有“/useraccount/edit/1”或“/useraccount/edit?id=1”的页面。使用 UrlHelper Action 方法生成 url 时,如果将 id 作为查询字符串参数传递,则 id 值不包含在 RouteData 中。
new UrlHelper(helper.ViewContext.RequestContext).Action(
action, helper.ViewContext.RouteData.Values)
我正在寻找一种访问 id 值的一致方法,无论使用哪个 url 访问页面,或者一种自定义 RouteData 对象初始化的方法,以便它检查缺少路由参数的查询字符串,如果找到则添加它们。
您可以使用
@Url.RouteUrl("Default", new { id = ViewContext.RouteData.Values["id"] != null ? ViewContext.RouteData.Values["id"] : Request.QueryString["id"] })
试试这个解决方案
var qs = helper.ViewContext
.HttpContext.Request.QueryString
.ToPairs()
.Union(helper.ViewContext.RouteData.Values)
.ToDictionary(x => x.Key, x => x.Value);
var rvd = new RouteValueDictionary(qs);
return new UrlHelper( helper.ViewContext.RequestContext).Action(action, rvd);
转换 NameValueCollection 试试这个
public static IEnumerable<KeyValuePair<string, object>> ToPairs(this NameValueCollection collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
return collection.Cast<string>().Select(key => new KeyValuePair<string, object>(key, collection[key]));
}
Extending Route 最终成为满足我需求的最简单的解决方案;感谢你的建议!让我知道我的解决方案是否有任何明显的问题(class 名称除外)。
FrameworkRoute.cs
public class FrameworkRoute: Route
{
public FrameworkRoute(string url, object defaults) :
base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
{
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
if (routeData != null)
{
foreach (var item in routeData.Values.Where(rv => rv.Value == UrlParameter.Optional).ToList())
{
var val = httpContext.Request.QueryString[item.Key];
if (!string.IsNullOrWhiteSpace(val))
{
routeData.Values[item.Key] = val;
}
}
}
return routeData;
}
}
Global.asax.cs
protected override void Application_Start()
{
// register route
routes.Add(new FrameworkRoute("{controller}/{action}/{id}", new { controller = "Portal", action = "Index", id = UrlParameter.Optional }));