我有一个显示项目列表的部分视图,我在几个不同的地方使用这个局部视图。在这个局部视图中,我使用了一个分页器 -
@Html.PagedListPager(Model, page => Url.Action(null, new { page = page }))
这导致paginator显示我正在查看的Action和View的页面URL。
问题是,在我的搜索页面上,我使用查询字符串作为搜索字符串,而Url.Action方法不包含现有的查询字符串参数。
而不是/ Search?s = bla& page = 3我最终使用/ Search?page = 3
如何使用现有查询字符串生成网址?
编辑:
这是我的代码
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(
"Search",
new SearchRoute("Search", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(
new { controller = "Search", action = "Index" })
});
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Call", action = "Index", id = UrlParameter.Optional }
);
}
public class SearchRoute : Route
{
public SearchRoute(string url, IRouteHandler routeHandler)
: base(url, routeHandler)
{
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
System.Diagnostics.Debug.WriteLine(Url);
if (HttpContext.Current != null)
{
string s = HttpContext.Current.Request.QueryString["s"];
if (!string.IsNullOrEmpty(s))
values.Add("s", s);
}
return base.GetVirtualPath(requestContext, values);
}
}
答案 0 :(得分:3)
使用自定义路由,您可以保留查询字符串,因为大多数Url生成逻辑使用该路由生成URL。在这种情况下,我正在检查Request对象中是否有一个名为XXX的查询字符串,并将其添加到路径中(如果存在),如果您愿意,可以使其更通用。
using System.Web;
using System.Web.Routing;
public class PreserveQueryStringRoute : Route
{
public PreserveQueryStringRoute(string url, IRouteHandler routeHandler)
: base(url, routeHandler)
{
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
if(HttpContext.Current != null)
{
values = new RouteValueDictionary(values); //this is the bug fix!
if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["XXX"]))
values.Add("XXX", HttpContext.Current.Request.QueryString["XXX"]);
}
var path = base.GetVirtualPath(requestContext, values);
return path;
}
}
在global.ascx中按正常方式注册路线(尽管可能不是我下面的通用匹配)
routes.Add(
"Default",
new PreserveQueryStringRoute("{controller}/{action}/{id}", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(
new { controller = "Home", action = "Index", id = UrlParameter.Optional })
});
编辑:
好的,这是一个更新..它是一个错误修复,以及如何注册路由的示例(请参阅上面的更正代码以修复错误)
以下是如何注册:
routes.Add(
"Search",
new SearchRoute("Search", new MvcRouteHandler())
{
Constraints = new RouteValueDictionary(
new { controller = "Search", action = "Index" })
});
答案 1 :(得分:0)
我是这样做的:
我已经实现了一些扩展方法,将查询字符串转换为RouteValueDictionary
并在其中设置单独的项目:
public static class RouteValueDictionaryExtensions
{
public static RouteValueDictionary ToRouteValues(this NameValueCollection queryString)
{
if (queryString == null || queryString.HasKeys() == false)
return new RouteValueDictionary();
var routeValues = new RouteValueDictionary();
foreach (string key in queryString.AllKeys)
routeValues.Add(key, queryString[key]);
return routeValues;
}
public static RouteValueDictionary Set(this RouteValueDictionary routeValues, string key, string value)
{
routeValues[key] = value;
return routeValues;
}
public static RouteValueDictionary Merge(this RouteValueDictionary primary, RouteValueDictionary secondary)
{
if (primary == null || primary.Count == 0)
{
return secondary ?? new RouteValueDictionary();
}
if (secondary == null || secondary.Count == 0)
return primary;
foreach (var pair in secondary)
primary[pair.Key] = pair.Value;
return primary;
}
public static RouteValueDictionary Merge(this RouteValueDictionary primary, object secondary)
{
return Merge(primary, new RouteValueDictionary(secondary));
}
}
这样就可以创建如下链接:
Url.RouteUrl(Request.QueryString.ToRouteValues().Set("Key", "Value"))
或者这个:
Url.RouteUrl(Request.QueryString.ToRouteValues().Merge(new {key = "value"}))
我还可以链接这些扩展方法以获得更大的灵活性:
Url.RouteUrl(Request.QueryString.ToRouteValues().Set("Key", "Value").Set("AnotherKey", "AnotherValue"))