要继续我之前的一个问题(生成传出 url 时选择了意外路由),请考虑以下路由(无默认值,无约束):
"{controller}/{month}-{year}/{action}/{user}"
假设在通过与此路由匹配的传入 url 呈现某些页面时(因此请求上下文包含每个路由段的值),我需要生成一个仅更改month
和的 url,并year
保留所有其他段的确切值。
根据规则,我在链接的问题中提到(即路由系统将仅重用在 URL 模式中出现的段变量的值,而不是提供的任何参数。),如果我指定新的month
并且year
仅通过匿名对象,我会失去user
段的价值(即路线甚至不匹配)。
我知道有两种方法可以克服这个问题:
根本不要指定匿名对象;
context.RouteData.Values
但在;中设置必要的段值 生成所需的url后,返回原始值,以便使用原始请求段值执行其余页面渲染;这看起来像这样:public static MvcHtmlString GetDateUrl(this RequestContext context, DateTime date) { UrlHelper url = new UrlHelper(context); object month = null, year = null; if (context.RouteData.Values.ContainsKey("month")) { month = context.RouteData.Values["month"]; year = context.RouteData.Values["year"]; } try { context.RouteData.Values["month"] = date.Month; context.RouteData.Values["year"] = date.Year; return MvcHtmlString.Create( url.Action((string)context.RouteData.Values["action"])); } finally { if (month == null) { if (context.RouteData.Values.ContainsKey("month")) { context.RouteData.Values.Remove("month"); context.RouteData.Values.Remove("year"); } } else { context.RouteData.Values["month"] = month; context.RouteData.Values["year"] = year; } } }
RouteValueDictionary
根据当前请求上下文,使用 , 而不是匿名对象:public static MvcHtmlString GetDateUrl(this RequestContext context, DateTime date) { UrlHelper url = new UrlHelper(context); var values = new RouteValueDictionary(context.RouteData.Values); values["month"] = date.Month; values["year"] = date.Year; string action = (string)context.RouteData.Values["action"]; return MvcHtmlString.Create(url.Action(action, values)); }
第二个选项似乎更简短,而第一个不创建额外的字典,操纵请求上下文。
哪种方式更好?或者,也许我正在做/理解错误的事情?
Sanderson S., Freeman A. - Pro ASP.NET MVC 3 Framework(第 3 版)说不要依赖段值重用,而是指定在确切的地点和时间需要的所有值。
我展示了我发现执行此任务的方式,但是如果替换的段发生在路线的早期,那么替换段值的正确(或更好)方法是什么,保留其他值?
编辑
根据 Jani Hyytiäinen 的回答。所讨论的路线只是一个例子。目标 mvc 应用程序包含不同的路由,有些可能比这个更复杂。所以我正在寻找的方法应该能够与它们中的任何一个一起使用。我想说这个扩展方法只知道,它必须改变month
and year
,同时保留所有其他段。其他段的数量是任意的。所以硬编码它们根本不是一个可能的解决方案。除了请求上下文本身之外,我还有当前段值的来源。