带约束的属性路由
Attribute Routing with Constraint
如果我有这样的 ActionResult 方法:
public ActionResult AllSummaries(int? page, DateTime? yesterday)
而不是像这样的路线:
http://serverName/projectName/controllerName/AllSummaries?yesterday=04/03/2017
我希望它是:
http://serverName/projectName/controllerName/AllSummaries/04/03/2017
因此,在 ActionResult 之上,我如何添加约束以使日期时间仅以 MM/dd/yyyy
格式显示日期?
[Route("allsummaries/yesterday/{yesterday:}")]
public ActionResult AllSummaries(int? page, DateTime? yesterday)
我不需要验证日期和日期是 1 位还是 2 位。它总是 2 位。
感谢任何帮助。
更新
现在出现 404 错误:
这是我正在使用的link:
http://serverName/projectName/controllerName/allsummaries/yesterday/3/4/2017
这是我的操作:
[Route("controllerName/allsummaries/yesterday/{month?}/{day?}/{year?}")]
[ValidateInput(false)]
public ActionResult AllSummaries(int? page, int? day, int? month, int? year)
{
if (day.HasValue && month.HasValue && year.HasValue)
{
var yesterday = new DateTime(year.Value, month.Value, day.Value);
}
我生成的路由来自控制台应用程序,它将通过 windows 服务自动发送电子邮件,所以我不能使用 @Url.Action
...等等。我像这样对 link 进行硬编码:
mail.Body = mail.Body + "<div>" + "<p>" +
"http://serverName/projectName/controllerName/allsummaries/yesterday/" +
DateTime.Today.AddDays(-1).Day +
"/" + DateTime.Today.AddDays(-1).Month + "/" +
DateTime.Today.AddDays(-1).Year + "</p>" + "</div>";
可以单独解析日月年,
然后创建日期。
您的代码将是这样的:
[Route("allsummaries/yesterday/{day}/{month}/{year}")]
public ActionResult AllSummaries(int? page, int day, int month, int year)
{
var yesterday = new Date(day, month, year);
}
[Route("allsummaries/yesterday")]
public ActionResult AllSumaries(int? page)
{
}
问题是日期中的斜线,它将被解释为路径分隔符。路由框架只解析路径分隔符之间的参数,除非你使用贪婪的参数语法,即 {*yesterday}
。但是,如果您这样做,URL 路径的任何其他部分都将被消耗。例如,如果用户将 URL 更改为 allsummaries/yesterday/04/03/2017/foo
之类的内容,则 04/03/2017/foo
将作为 yesterday
传入,并且您的操作会爆炸。
你有两个选择。
您可以使用不同的日期格式,例如 ISO:yyyy-MM-dd
,这将使您的 URL /allsummaries/yesteday/2017-04-03
,并且您可以捕获日期部分单个参数:{yesterday}
.
[Route("allsummaries/yesterday/{yesterday}")]
您可以分解日期组件,然后在操作中将它们重组为 DateTime
:
[Route("allsummaries/yesterday/{month?}/{day?}/{year?}")]
然后,在您的操作中:
public ActionResult AllSummaries(int? page, int? month, int? day, int? year)
{
var yesterday = DateTime.Today.AddDays(-1); // default
if (month.HasValue && day.HasValue && year.HasValue)
{
yesterday = new DateTime(year.Value, month.Value, day.Value);
}
编辑
我不想混淆主要问题,但如果您选择遵循第二个选项,将日期分解为多个部分,则需要注意一个问题。如果你有像 /allsummaries/yesterday/04/03/2017
这样的显式 URL,模型绑定器将能够将“04”和“03”解析为 int
。但是,如果您尝试 创建 URL,使用 Url.Action
、Url.RouteUrl
等,您将需要提供参数值像“04”,而不是一个整数,否则你最终会得到像 /allsummaries/yesterday/4/3/2017
这样的 URL。你可以通过类似的方式做到这一点:
@Url.Action("AllSummaries", new
{
month = date.ToString("MM"),
day = date.ToString("dd"),
year = date.Year
})
换句话说,您需要使用ToString
来获取两位数的值,而不是直接使用date.Month
或date.Day
。
您可能还应该通过向这些参数添加正则表达式约束来保护 URL 免受篡改:
[Route("allsummaries/yesterday/{month?:regex([0-9]{2})}/{day?:regex([0-9]{2})}/{year?:regex([0-9]{4}}")]
如果我有这样的 ActionResult 方法:
public ActionResult AllSummaries(int? page, DateTime? yesterday)
而不是像这样的路线:
http://serverName/projectName/controllerName/AllSummaries?yesterday=04/03/2017
我希望它是:
http://serverName/projectName/controllerName/AllSummaries/04/03/2017
因此,在 ActionResult 之上,我如何添加约束以使日期时间仅以 MM/dd/yyyy
格式显示日期?
[Route("allsummaries/yesterday/{yesterday:}")]
public ActionResult AllSummaries(int? page, DateTime? yesterday)
我不需要验证日期和日期是 1 位还是 2 位。它总是 2 位。
感谢任何帮助。
更新
现在出现 404 错误:
这是我正在使用的link:
http://serverName/projectName/controllerName/allsummaries/yesterday/3/4/2017
这是我的操作:
[Route("controllerName/allsummaries/yesterday/{month?}/{day?}/{year?}")]
[ValidateInput(false)]
public ActionResult AllSummaries(int? page, int? day, int? month, int? year)
{
if (day.HasValue && month.HasValue && year.HasValue)
{
var yesterday = new DateTime(year.Value, month.Value, day.Value);
}
我生成的路由来自控制台应用程序,它将通过 windows 服务自动发送电子邮件,所以我不能使用 @Url.Action
...等等。我像这样对 link 进行硬编码:
mail.Body = mail.Body + "<div>" + "<p>" +
"http://serverName/projectName/controllerName/allsummaries/yesterday/" +
DateTime.Today.AddDays(-1).Day +
"/" + DateTime.Today.AddDays(-1).Month + "/" +
DateTime.Today.AddDays(-1).Year + "</p>" + "</div>";
可以单独解析日月年, 然后创建日期。
您的代码将是这样的:
[Route("allsummaries/yesterday/{day}/{month}/{year}")]
public ActionResult AllSummaries(int? page, int day, int month, int year)
{
var yesterday = new Date(day, month, year);
}
[Route("allsummaries/yesterday")]
public ActionResult AllSumaries(int? page)
{
}
问题是日期中的斜线,它将被解释为路径分隔符。路由框架只解析路径分隔符之间的参数,除非你使用贪婪的参数语法,即 {*yesterday}
。但是,如果您这样做,URL 路径的任何其他部分都将被消耗。例如,如果用户将 URL 更改为 allsummaries/yesterday/04/03/2017/foo
之类的内容,则 04/03/2017/foo
将作为 yesterday
传入,并且您的操作会爆炸。
你有两个选择。
您可以使用不同的日期格式,例如 ISO:
yyyy-MM-dd
,这将使您的 URL/allsummaries/yesteday/2017-04-03
,并且您可以捕获日期部分单个参数:{yesterday}
.[Route("allsummaries/yesterday/{yesterday}")]
您可以分解日期组件,然后在操作中将它们重组为
DateTime
:[Route("allsummaries/yesterday/{month?}/{day?}/{year?}")]
然后,在您的操作中:
public ActionResult AllSummaries(int? page, int? month, int? day, int? year) { var yesterday = DateTime.Today.AddDays(-1); // default if (month.HasValue && day.HasValue && year.HasValue) { yesterday = new DateTime(year.Value, month.Value, day.Value); }
编辑
我不想混淆主要问题,但如果您选择遵循第二个选项,将日期分解为多个部分,则需要注意一个问题。如果你有像 /allsummaries/yesterday/04/03/2017
这样的显式 URL,模型绑定器将能够将“04”和“03”解析为 int
。但是,如果您尝试 创建 URL,使用 Url.Action
、Url.RouteUrl
等,您将需要提供参数值像“04”,而不是一个整数,否则你最终会得到像 /allsummaries/yesterday/4/3/2017
这样的 URL。你可以通过类似的方式做到这一点:
@Url.Action("AllSummaries", new
{
month = date.ToString("MM"),
day = date.ToString("dd"),
year = date.Year
})
换句话说,您需要使用ToString
来获取两位数的值,而不是直接使用date.Month
或date.Day
。
您可能还应该通过向这些参数添加正则表达式约束来保护 URL 免受篡改:
[Route("allsummaries/yesterday/{month?:regex([0-9]{2})}/{day?:regex([0-9]{2})}/{year?:regex([0-9]{4}}")]