如何替换某些分段';保护他人的价值观
本文关键字:保护 价值观 分段 何替换 替换 | 更新日期: 2023-09-27 17:51:01
要继续我之前的一个问题(生成传出url时选择了意外路线(,请考虑以下路线(无默认值,无限制(:
"{controller}/{month}-{year}/{action}/{user}"
假设在通过与该路由匹配的传入url呈现某个页面时(因此请求上下文包含每个路由段的值(,我需要生成一个仅更改month
和year
的url,保留所有其他段的确切值。
根据我在链接问题中提到的规则(即路由系统将仅对URL模式中比提供的任何参数更早出现的段变量重用值。(,如果我仅通过匿名对象指定新的month
和year
,我将丢失user
段的值(即路由甚至不匹配(。
我知道有两种方法可以克服这个问题:
根本不要指定匿名对象;而是在CCD_ 6中设置必要的分段值;生成所需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(第三版(表示不要依赖分段值重用,而是要在确切的时间和地点指定所需的所有值。
我展示了我发现的完成这项任务的方法,但如果被替换的段在路线中出现得更早,那么替换段的值并保留其他值的正确(或更好(方法是什么?
编辑
根据Jani Hyytiäinen的回答。所讨论的路线只是一个例子。目标mvc应用程序包含不同的路由,有些可能比这一个更复杂。因此,我正在寻找的方法应该能够与他们中的任何一个合作。我想说,这个扩展方法只知道,它必须更改month
和year
,同时保留所有其他段。其他段的数目是任意的。因此,对所有这些进行硬编码根本不是一个可能的解决方案。此外,除了请求上下文本身,我还有当前段值的来源。
public static MvcHtmlString GetDateUrl(this RequestContext context, DateTime date)
{
var values = context.RouteData.values;
var data = new{
controller = values["controller"] ?? "Home";
action = values["action"] ?? "Index";
month = date.Month;
year = date.Year;
user = context.HttpContext.User.Identity.Name;
};
string url = UrlHelper.RouteUrl(data);
return MvcHtmlString.Create(url);
}
为什么要让它变得更复杂?你可能会争辩说你想对HttpContext进行一些null检查,但当你有一个没有HttpContext的RequestContext时,这里的null检查是你最小的问题。要么这样,要么你让一个程序员做一些非常时髦的事情,你确实希望应用程序在那里大放异彩,让他们知道他们正在做一些不起作用的事情,他们应该在它投入生产之前就停止。
您可能还需要在这里对其他内容进行额外的检查,但实际上,这种方法的责任到此为止。它应该接受一个日期,并以MvcHtmlString的形式返回一个路由url。时期
从性能角度来看,在生成url时,您可以在这里显式地定义一个特定的路由名称,但要做到这一点,您需要有一个相当大的路由集合。考虑到您将在这个方法和路由配置之间创建一个隐藏的依赖关系。有人更改路线名称的那天,应用程序就会崩溃,很难找到原因。
您可能还想使用RouteValueDictionary,但没有任何理由。若我没记错的话,UrlHelper无论如何都会在内部使用对象。即使我记错了,它也能为你转换它。
参考文献:"请在准确的地点和时间指定所有需要的值",Sanderson S.,Freeman A.-Pro ASP.NET MVC 3 Framework
http://msdn.microsoft.com/en-us/library/dd505226(v=vs.108(.aspx