1

有没有办法从另一个模块中调用 NancyFX 动作?

public class FirstModule : NancyModule
{
    public FirstModule()
    {

        Post["/FirstMethod/{id}"] = parameters =>
        {
            var response =  <Call second module and SecondMethod>;
            return View["blah"]
        }; 
    }
}

然后在第二个模块上调用一个方法:

public class SecondModule : NancyModule
{
    public SecondModule()
    {
        Post["SecondMethod/{id}"] = parameters =>
        {
            Do some stuff....
        };
    }
4

3 回答 3

3

正如其他评论者所指出的,这样做似乎是一种设计气味。不管 ...

更改 SecondModule 的代码,如下所示:

public class SecondModule : NancyModule
{
    public SecondModule()
    {
        Post["SecondMethod/{id}"] = SecondMethod;
    }

    public object SecondMethod(dynamic p)
    {
        //Do some stuff...
    }

然后在您的第一个模块中,只需根据需要调用第二个模块:

Post["/FirstMethod/{id}"] = parameters =>
{
    var secondModule = new SecondModule(); //use dependency injection in real code 
    var response =  secondModule.SecondMethod(parameters);
    return View["blah"]
}; 

当然,正如@Christian 所提到的,最好的方法是将公共代码移出一个完全独立的类,并让两个模块都调用它。

于 2014-01-09T21:12:35.300 回答
3

我正在寻找如何将控制从一个动作传递到另一个模块中的另一个动作,这是我最接近实际答案的方法。以防万一它对其他人有帮助,这是我发现的一般情况。

这样做的好处是它允许通过同一个 url 访问多个模块中的多个操作,但将事物封装在最合乎逻辑的位置。

在源(传递控制的那个)动作中:

public class IndexModule : BaseModule
{
    public IndexModule()
    {
        Get["/"] = parameters =>
        {
            // Here we want to handoff to the default action in another module; this keeps the URL the same
            var itemController = new DbItemModule { Context = this.Context };
            parameters.itemId = 5; // Specific item to load in target
            return itemController.itemHomeSharedLogic(parameters);
        }
    }
}

在目标模块中:

public class DbItemModule : BaseModule
{
    public GeneralModule() : base("/item")
    {
        Get["/{itemId}"] = parameters => itemHomeSharedLogic(parameters);
    }

    /// <summary>
    /// This is factored out of the /item/{itemId} route so it can be shared with IndexModule's default route.
    /// </summary>
    /// <param name="parameters">Object with (int)itemId property set for the item to show.</param>
    /// <returns>Value of the GET action handler for an item's homepage.</returns>
    ///
    public Negotiator itemHomeSharedLogic(dynamic parameters)
    {
        dynamic model = new ExpandoObject();
        // ...set model properties...

        return View["db/item/index", model];

    } // itemHomeSharedLogic
}
于 2015-06-10T21:04:17.647 回答
1

我同意设计一个 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"]
    }; 
  }
}
于 2017-04-21T19:10:03.400 回答