2013-05-28 10 views
2

У меня есть класс обслуживания, который необходим для создания pdf-файла, который требуется для ввода ControllerContext, чтобы отобразить html => pdf. Эта услуга вызывается через средний уровень, который не имеет ссылки на проект web/mvc. это хорошо, так как Ninject делает все необходимые инъекции услуг и т.д. Это то, что служба выглядит (упрощенный для этих целей)Контекст Bind Controller с 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 (интермедиат идентификатор) вызывает:
MiddleTier.BusinessLogic.SendEmailWithPdf (интермедиат идентификатор) вызывает:
Web.Services.PdfCreatorService.CreateReport (интермедиат идентификатор)

Ninject достигает PdfCreatorService, никаких проблем, но: мне нужно как-то переслать ControllerContext с HomeController (через средний уровень) в PdfCreatorService. Пока средний уровень не может ссылаться на ControllerContext.

Я смотрел Провайдеры, Заводы, Резольвер и т. Д. Но не смог найти правильное решение.

Любая помощь приветствуется! Cheers

+0

Вы звоните в PdfCreatorService из своего контроллера? Если это так, почему бы вам просто не передать параметр controlcontext в качестве параметра. Или даже лучше с точки зрения дизайна, извлеките необходимую информацию и передайте ее в качестве простых параметров для вашего PdfCreatorService. – Kenneth

+0

@ Kenneth no, как показано в стеке, я не вызываю PdfCreatorService непосредственно из контроллера. Можете ли вы объяснить, как использовать простой параметр для передачи ControllerContext? – Sam7

+0

Итак, вы получаете это от веб-службы? Если это так, так как вы не вызываете контроллер, не будет также доступ к содержимому контроллера. – Kenneth

ответ

3

OK. Я придумал решение, которым я доволен.
Вот как я извлекая 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(); 
    } 
} 

По-прежнему интересно узнать, есть ли у кого более элегантное решение.

2

Вы можете создать фабрику Custom Controller.

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); 
+0

Спасибо за ответ. Это немного похоже на обман. Так как вы просто сохраняете его в HttpContext.Current.Request. Таким образом, в обход ниндже. Ninject почти избыточен, поскольку PdfService может просто загрузить его из HttpContext.Current.Request без ninject ... – Sam7

Смежные вопросы