有没有办法在ASP.NET 5中获取当前的控制器实例?

时间:2015-08-28 00:24:19

标签: asp.net asp.net-core asp.net-core-mvc

有没有办法用DI做到这一点?我试过IScopedInstance<Controller>,但这给了我null。围绕aspnet的源代码,但没有获胜。有什么想法吗?

我有一个接受不同IPaymentMethod的控制器。 IPaymentMethod 可以可以呈现视图的ViewComponent。如果IPaymentMethodViewComponent,我希望它在帖子后面使用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();
}

2 个答案:

答案 0 :(得分: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的{​​{1}}可能仍为空。

答案 1 :(得分: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);
}