2

我继承了一个 WCF 项目,其中包含一些我需要迁移到一个新的 NancyFx 项目中的糟糕构造的路由(这些路由有效)。我需要能够在我的 Nancy 应用程序中定义响应相同 GET 请求的路由。我暂时无法更改路线。

在 WCF 项目中,一个 GET 请求...

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

匹配这个 UriTemplate:

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


我希望这将是南希的等价物

Get["/GetUsers?UserId={userId}&Language={language}"] = p => { ... }

但相同的 GET 请求会导致 404。

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

我知道这很可怕,但它是暂时的,直到我可以安排时间与我们的 UI 团队一起重写前端以调用正确的完整 URL。

4

2 回答 2

8

约翰,

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

Query 属性返回 a 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);
}

希望这可以帮助!

于 2012-09-21T21:13:23.630 回答
5

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

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));
}

这使我能够删除验证 Query 和 Form 值的仪式代码(当我记得这样做时,并不是每次都这样做)。所以你会得到更简洁的代码,更容易阅读,更容易记住首先进行检查,例如:

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   
};
于 2012-09-22T17:03:33.750 回答