带约束的属性路由

时间:2017-04-04 15:08:40

标签: c# asp.net-mvc-5 attributerouting

如果我有一个像这样的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错误:

以下是我正在使用的链接:

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 ...等等。我正在硬编码这样的链接:

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>";

2 个答案:

答案 0 :(得分:1)

问题是日期中的斜杠,它将被解释为路径分隔符。路由框架仅解析路径分隔符之间的参数,除非您使用贪婪的参数语法,即{*yesterday}。但是,如果您这样做,将消耗URL路径的任何其他部分。例如,如果用户将网址更改为allsummaries/yesterday/04/03/2017/foo,则04/03/2017/foo会以yesterday的形式传入,您的操作会爆炸。

您有两种选择。

  1. 您可以使用不同的日期格式,例如ISO:yyyy-MM-dd,它会生成您的网址/allsummaries/yesteday/2017-04-03,您可以使用单个参数捕获日期部分:{{1} }。

    {yesterday}
  2. 您可以拆分日期组件,然后在操作中将它们重新组合为[Route("allsummaries/yesterday/{yesterday}")]

    DateTime

    然后,在你的行动中:

    [Route("allsummaries/yesterday/{month?}/{day?}/{year?}")]
    
  3. 修改

    我不想混淆主要问题,但如果您选择遵循第二个选项,将日期分解为组件,则需要注意一个问题。如果您有明确的网址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); } ,则模型绑定器将能够将“04”和“03”解析为/allsummaries/yesterday/04/03/2017。但是,如果您尝试创建网址,使用intUrl.Action等内容,则需要提供类似“04”的参数值,而不是一个int,或者你最终会得到像Url.RouteUrl这样的网址。你可以通过以下方式做到这一点:

    /allsummaries/yesterday/4/3/2017

    换句话说,您需要使用@Url.Action("AllSummaries", new { month = date.ToString("MM"), day = date.ToString("dd"), year = date.Year }) 来获取两位数值,而不是ToStringdate.Month

    您还应该通过在这些参数上添加正则表达式约束来保护URL免受篡改:

    date.Day

答案 1 :(得分:0)

您可以单独解析日,月和年, 然后创建日期。

您的代码将是这样的:

[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)
{
}