Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用Ninject绑定控制器上下文_C#_Asp.net Mvc_Asp.net Mvc 4_Ninject_Ninject 2 - Fatal编程技术网

C# 用Ninject绑定控制器上下文

C# 用Ninject绑定控制器上下文,c#,asp.net-mvc,asp.net-mvc-4,ninject,ninject-2,C#,Asp.net Mvc,Asp.net Mvc 4,Ninject,Ninject 2,我有一个创建pdf所需的服务类,它需要注入ControllerContext,以便呈现html=>pdf。 该服务是通过中间层调用的,中间层没有对web/mvc项目的引用。这很好,因为ninject完成了所有必需的服务注入等。 这就是服务的外观(为了这些目的而简化) 以下是简化的调用堆栈: Web.HomeController.SendEmailWithPdf(int-id)调用: MiddleTier.BusinessLogic.SendEmailWithPdf(int-id)调用: Web.

我有一个创建pdf所需的服务类,它需要注入ControllerContext,以便呈现
html=>pdf
。 该服务是通过中间层调用的,中间层没有对web/mvc项目的引用。这很好,因为ninject完成了所有必需的服务注入等。 这就是服务的外观(为了这些目的而简化)

以下是简化的调用堆栈:

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

Ninject正在访问PdfCreatorService,没有问题,但是:我需要以某种方式将ControllerContext从HomeController(通过中间层)转发到PdfCreatorService。 而中间层不能引用ControllerContext

我看过提供商、工厂、解析器等。 但是找不到正确的解决方案

感谢您的帮助!
干杯

您可以创建一个自定义控制器工厂

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);
kernel.Bind();

好的。我想出了一个我满意的解决方案。
以下是我检索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);
    }
}
这是provider类的外观:

public class ControllerContextProvider
{
    public Func<ControllerContext> GetControllerContext { get; set; }
}
公共类ControllerContextProvider
{
公共函数GetControllerContext{get;set;}
}
这就是我绑定它的方式:

public class PortalNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<ControllerContextProvider>().ToSelf().InRequestScope();
    }
}
公共类PortalInjectModule:NinjectModule
{
公共覆盖无效负载()
{
Bind().ToSelf().InRequestScope();
}
}

仍然有兴趣查看是否有人有更优雅的解决方案。

您是否从控制器调用PdfCreatorService?如果是这样,为什么不将controllercontext作为参数传递呢。或者从设计的角度来看,更好的做法是提取所需的信息,并将其作为简单参数传递给PdfCreatorService。@Kenneth否,如堆栈中所示,我不是直接从控制器调用PdfCreatorService。你能解释一下,我将如何使用一个简单的参数来传递ControllerContext吗?那么你是从一个web服务访问它的?如果是这样,由于您没有调用控制器,因此也不会有可用的controllercontext。我正在调用controller->middle tier->pdfService,但中间层无法引用controllercontext。谢谢您的回答。但这感觉有点像作弊。因为您只是将其保存到HttpContext.Current.Request中。所以有点绕过ninject。Ninject几乎是冗余的,因为PdfService可以只从HttpContext.Current.Request加载它,而不使用Ninject。。。
public class PortalNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<ControllerContextProvider>().ToSelf().InRequestScope();
    }
}