我同意设计一个 Nancy 应用程序,其中一条路由需要直接调用另一条路由是不好的做法。但是,我有一个相关但不同的场景。我有一个应用程序,其中许多路由代表数据库中的项目。这些路由可能采用/{type}/{guidPrimaryKey}
或/{type}/{humanReadableKey}
什至的形式/{type}/{humanReadableKey}/rev/{revision}
。考虑一个表单,用户需要告诉服务器要使用数据库中的哪个项目。除了搜索功能之外,我还希望用户能够粘贴代表数据库项目的 URL。我不希望在多个位置拥有所有不同 URL 结构的代码逻辑,因此最好将 URL 作为参数传递给一个路由并从它所代表的路由中获取响应。经过一番黑客攻击,我找到了一个可行的解决方案。
创建一个类来计算依赖于核心 Nancy 路由接口的响应
public class UrlDispatcher
{
private IRequestDispatcher _dispatcher;
private INancyContextFactory _contextFactory;
public UrlDispatcher(IRequestDispatcher dispatcher
, INancyContextFactory contextFactory)
{
_dispatcher = dispatcher;
_contextFactory = contextFactory;
}
public async Task<Response> GetResponse(NancyContext context
, string url, CancellationToken ct)
{
var request = new Request("GET", new Url(url), null
, context.Request.Headers.ToDictionary(k => k.Key, k => k.Value));
var ctx = _contextFactory.Create(request);
return _dispatcher.Dispatch(ctx, ct);
}
}
在您的引导程序类中,实例化并存储此实用程序类的副本
public class Bootstrapper : Nancy.Hosting.Aspnet.DefaultNancyAspNetBootstrapper
{
private static UrlDispatcher _dispatcher;
public static UrlDispatcher Dispatcher { get { return _dispatcher; } }
protected override void ApplicationStartup(Nancy.TinyIoc.TinyIoCContainer container
, Nancy.Bootstrapper.IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
_dispatcher = container.Resolve<UrlDispatcher>();
}
}
然后,从您的模块中,代码看起来像
public class FirstModule : NancyModule
{
public FirstModule()
{
Post["/FirstMethod/{id}", true] = async (parameters, ct) =>
{
var response = await Bootstrapper.Dispatcher.GetResponse(this.Context
, "http://test/SecondMethod/" + (string)parameters.id, ct);
return View["blah"]
};
}
}