2015-08-28 2 views
1

Есть ли способ сделать это с помощью DI? Я попробовал IScopedInstance<Controller>, но это дает мне null. Пытался по исходному коду aspnet, но не выиграл. Есть идеи?Есть ли способ получить текущий экземпляр контроллера в ASP.NET 5?

У меня есть контроллер, который принимает разные IPaymentMethod s. IPaymentMethodcan be ViewComponentcan render Views. Если является ViewComponent, я хочу, чтобы он использовал встроенную привязку модели MVC для обратной связи.

public class XController : Controller 
{ 

    // ctor, props, ... 

    public IActionResult Checkout() 
    { 
     return View(new Model 
     { 
      PaymentMethodId = 1, 
      PaymentMethodType = typeof(MyPaymentMethod) // The razor file will use this type to render it as a ViewComponent 
     }); 
    } 

    [HttpPost] 
    public IActionResult Checkout(Model model) 
    { 
     var paymentMethod = _paymentService.GetPaymentMethodById(model.PaymentMethodId); 

     paymentMethod.ProcessPayment(); 

     // .. 
    } 
} 

Это то, где мне нужен контроллер для инъекции. Я хотел использовать встроенную проверку MVC и привязку модели.

public class MyPaymentMethod : IPaymentMethod 
{ 
    private Controller _currentController; 

    public MyPaymentMethod(IScopedInstance<Controller> controller) 
    { 
     _currentController = controller.Value; 
    } 

    public void ProcessPayment() 
    { 
     var model = new PaymentModel(); 

     _currentController.TryUpdateModel(model, typeof(PaymentModel), null); 

     if (!_currentController.ModelState.IsValid) 
     { 
      return; // or exception 
     } 

     // Process Payment using model 
    } 

    public Task<IViewComponentResult> InvokeAsync() 
    { 
     // returns View 
    } 
} 

public interface IPaymentMethod 
{ 
    void ProcessPayment(); 
} 
+0

Просим предоставить дополнительную информацию. Из какой области или контекста вы пытаетесь получить текущий контроллер? – Dai

+4

Обратите внимание, что вся точка ослабления связи и разъединения состоит в том, что другие слои в вашем приложении должны быть полностью не осведомлены о текущем контроллере. – Dai

+0

@ Дай Правда. Это исключение, хотя из-за того, что класс находится в «сетевом» слое. – Dealdiane

ответ

0

Это больше не работает с beta7

В это время написания (beta6), это, вероятно, не поддерживается, и есть веские причины для этого: контроллеры в ASP.NET 5 делает не нужно наследовать от класса Controller. Однако я нашел способ работать с ActionFilters.

public class ScopeControllerActionFilterAttribute : ActionFilterAttribute 
{ 
    private readonly IScopedInstance<Controller> _controller; 

    public ScopeControllerActionFilterAttribute(IScopedInstance<Controller> controller) 
    { 
     _controller = controller; 
    } 


    public override void OnActionExecuting(ActionExecutingContext context) 
    { 
     if (_controller.Value == null) 
     { 
      _controller.Value = context.Controller as Controller; 
     } 
    } 
} 

Обратите внимание, что в зависимости от стадии жизненного цикла запроса HTTP, то Value из IScopedInstance<Controller> еще может быть пустым.

0

Поскольку экземпляр модели требуется в методе ProcessPayment, почему бы просто не передать его в качестве параметра?

[HttpPost] 
public IActionResult Checkout(PaymentModel model) 
{ 
    var paymentMethod = _paymentService.GetPaymentMethodById(model.PaymentMethodId); 

    if (!ModelState.IsValid) 
    { 
     return; // or exception 
    } 

    paymentMethod.ProcessPayment(model); 

    // .. 
} 

public void ProcessPayment(PaymentModel model) 
{ 
    // Process Payment using model 
} 

Ваша служба берет на себя обязанности, которые принадлежат к контроллеру, а именно - проверка ModelState.IsValid.

public interface IPaymentMethod 
{ 
    void ProcessPayment(PaymentModel model); 
} 

Вы можете также передать только те свойства, которые необходимы от модели оплаты, или вы можете сделать интерфейс IPaymentModel разъединить вашу модель из вашего PaymentService. В этом случае ваш IPaymentModel перейдет в общий уровень.

public interface IPaymentMethod 
{ 
    void ProcessPayment(IPaymentModel model); 
} 
+0

Это был первый вариант, но был быстро удален из-за того, как реализованы слои. В реальном проекте есть IPaymentService, который может принимать любой метод IPaymentMethod. IPaymentService вызовет метод ProcessPayment для пройденного метода IPaymentMethod. IPaymentService не может ссылаться на какой-либо компонент _HTTP_. Я просто оставил эту часть в моем примере ради простоты. – Dealdiane

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