Nancy Routes导致404

时间:2012-09-21 20:33:53

标签: wcf http-status-code-404 nancy

我继承了一个WCF项目,其中包含一些构建错误的路由(可以工作),我需要迁移到新的NancyFx项目中。我需要能够在我的Nancy应用程序中定义响应相同GET请求的路由。我暂时无法改变路线。

在WCF项目中,GET请求为...

http://localhost:12345/webapi/GetUsers?UserId=567&Language=en

匹配此UriTemplate:

UriTemplate = "GetUsers?UserId={userId}&Language={language}


我希望这在Nancy

中是等价的
Get["/GetUsers?UserId={userId}&Language={language}"] = p => { ... }

但是相同的GET请求会产生404。

有没有办法构建我的Nancy路由来响应这个GET请求?如果没有,任何解决方法?

我知道这很糟糕,但它是暂时的,直到我可以安排时间与我们的UI团队重写前端以调用正确的休息完整网址。

2 个答案:

答案 0 :(得分:8)

约翰,

您的路线是/GetUsers(顺便说一下,您如何处理/webapi部分?这是您的应用程序的基本网址还是您正在设置模块路径?)并且您会阅读使用Request.Query成员的查询字符串。

Query属性返回DynamicDictionary,您可以使用属性Request.Query.UserId或字典Request.Query["UserId"]

来访问值

您无法使查询字符串成为需要匹配的模式的一部分,以便调用路由。如果你真的想要,你可以做的是使用路由条件,这是路由声明中的第二个参数。这使您可以控制谓词,该谓词确定路径是否可以使用。所以你可以做这样的事情

Get["/GetUsers", ctx => ctx.Request.Query.UserId.HasValue && ctx.Request.Query.Language.HasValue] = p {... }

然后你可以将它全部重构为NancyContext上的扩展方法,使其更加整洁

Get["/GetUsers", ctx => ctx.HasQueryValues("UserId", "Language")] = p {... }

并使扩展名像

public static bool HasQueryValues(this NancyContext context, params string[] values)
{
   return values.All(x => context.Request.Query[x].HasValue);
}

希望这有帮助!

答案 1 :(得分:5)

继@TheCodeJunkie的回答之后,我有点过度兴奋,因为他想扩展NancyContext以提供预先检查Query值以确保请求有效的路由条件。我进一步扩展了NancyContext以对Form值,Header集合甚至Files集合进行相同的预检查,如下所示:

public static bool HasQuery(this NancyContext context, params string[] values)
{
    var query = context.Request.Query;
    return values.All(value => query[value].HasValue);
}

public static bool HasForm(this NancyContext context, params string[] values)
{
    var form = context.Request.Form;
    return values.All(value => form[value].HasValue);
}

public static bool HasHeader(this NancyContext context, params string[] values)
{
    var headers = context.Request.Headers;
    return values.All(value => !headers[value].FirstOrDefault().IsEmpty());
}

public static bool HasFile(this NancyContext context, params string[] values)
{
    var files = context.Request.Files;
    return values.All(value => files.Any(file => file.Key == value));
}

这使我可以删除验证查询和表单值的仪式代码(当我记得这样做时,结果并非每次都这样)。因此,您可以获得更易于阅读且更易于记忆的清洁代码,例如:

<强>之前

Post["/"]=_=>
{
    var form = Request.Form;
    if (
        !form.username.HasValue ||
        !form.password.HasValue ||
        !form.email.HasValue ||
        !form.claim.HasValue)
    {
        return HttpStatusCode.UnprocessableEntity;
    }
    //process form values with confidence
}

<强>后

Post["/", ctx => ctx.HasForm("username", "password", "email", "claim")]=_=>
{
    //process form values with confidence   
};