簡體   English   中英

使用Ninject綁定控制器上下文

[英]Bind Controller Context with Ninject

我有一個服務類,需要創建一個pdf,需要注入ControllerContext,以呈現html => pdf 此服務通過中間層調用,該中間層沒有引用web / mvc項目。 這很好,因為ninject完成所有必需的服務注入等。這就是服務的樣子(為此目的而簡化)

public class PdfCreatorService : AbstractUrlBasedPdfCreatorService
{
    [Inject]
    public ControllerContext ControllerContext { get; set; }

    public override byte[] CreateReport(int reportId)
    {
        var result = new PdfController().CreateReport(reportId);
        using (var it = new ResponseCapture(ControllerContext.RequestContext))
        {
            result.ExecuteResult(ControllerContext);
            return it.ReadAllContents();
        }
    }
}

這是簡化的調用堆棧:

Web.HomeController.SendEmailWithPdf(int id)調用:
MiddleTier.BusinessLogic.SendEmailWithPdf(int id)調用:
Web.Services.PdfCreatorService.CreateReport(int id)

Ninject正在達到PdfCreatorService,沒問題,但是:我需要以某種方式將ControllerContext從HomeController(通過中間層)轉發到PdfCreatorService 雖然中間層不能對ControllerContext有任何引用。

我看過提供商,工廠,解析器等,但找不到合適的解決方案。

任何幫助表示贊賞! 干杯

好。 我想出了一個我很滿意的解決方案。
這是我正在檢索ControllerContext的方式:

public class PdfCreatorService 
{
    [Inject]
    public ControllerContextProvider contextProvider { get; set; }
    [Inject]
    public PdfController pdfController { get; set; }

    public override byte[] CreateReport(int reportId)
    {
        var context = contextProvider.GetControllerContext();
        using (var stream = new ResponseCapture(context.RequestContext))
        {
            // Setup Controller
            var routeData = new RouteData(context.RouteData.Route, context.RouteData.RouteHandler);
            routeData.Values.Add("action", "CreateReport");
            routeData.Values.Add("controller", "Pdf");
            routeData.Values.Add("id", reportId);
            var pdfContext = new ControllerContext(context.HttpContext, routeData, pdfController);

            // Execute Controller
            var result = pdfController.CreateReport(reportId);
            result.ExecuteResult(pdfContext);

            return stream.ReadAllContents();
        }
    }
}

這是在原始控制器中設置上下文的方法:

public abstract class HomeController : Controller
{
    [Inject]
    public ControllerContextProvider ControllerContextProvider { get; set; }

    protected override IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state)
    {
        ControllerContextProvider.GetControllerContext = () => ControllerContext;
        return base.BeginExecute(requestContext, callback, state);
    }
}

這就是提供者類的樣子:

public class ControllerContextProvider
{
    public Func<ControllerContext> GetControllerContext { get; set; }
}

這就是我綁定它的方式:

public class PortalNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<ControllerContextProvider>().ToSelf().InRequestScope();
    }
}

仍然有興趣看看是否有人有一個更優雅的解決方案。

您可以創建自定義控制器工廠。

public class MyControllerFactory : DefaultControllerFactory
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controller = base.CreateController(requestContext, controllerName);
        HttpContext.Current.Request["controllerInstance"] = controller;
        return controller;
    }
}

您需要在global.asax中注冊此控制器:

ControllerBuilder.Current.SetControllerFactory(typeof(MyControllerFactory));

之后,您可以配置Ninject以從請求中解析ControllerContext:

kernel.Bind<ControllerContext>().ToMethod(ctx => ((Controller)HttpContext.Current.Request["controllerInstance"]).ControllerContext);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM