dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.21k stars 9.95k forks source link

Best way to call a controller action method programatically and return IActionResult? #1543

Closed karthicksundararajan closed 7 years ago

karthicksundararajan commented 8 years ago

Hi folks,

I'm developing a open source CMS based on modular approach using ASP.NET Core RC2. I guess Areas are the best way to split the large application into small modules. Therefore, I've used areas as a modules in the CMS. Here, I would like to invoke the action method of a module (area).

1) In order to achieve that, I've created routing information manually and created action descriptor from that.

RouteContext context = new RouteContext(actionContext.HttpContext); context.RouteData = new RouteData(); context.RouteData.Values.Add("area", moduleContext.ModuleInfo.Name); context.RouteData.Values.Add("pageModuleId", moduleContext.PageModuleId); context.RouteData.Values.Add("controller", moduleAction.ControllerName); context.RouteData.Values.Add("action", moduleAction.ActionName); context.RouteData.PushState(actionContext.RouteData.Routers[0], null, null)

var actionDescriptor = actionSelector.Select(context); if (actionDescriptor == null) throw new NullReferenceException("Action cannot be located, please check whether module has been installed properly");

var moduleActionContext = new ActionContext(actionContext.HttpContext, context.RouteData, actionDescriptor);

var invoker = moduleInvokerProvider.CreateInvoker(moduleActionContext, actionDescriptor as ControllerActionDescriptor); var result = await invoker.InvokeAction() as ViewResult;null)

2) To invoke action and return IActionResult, I've used internal methods

var actionMethodInfo = _descriptor.MethodInfo;

var methodExecutor = _controllerActionMethodExecutor;

var arguments = ControllerActionExecutor.PrepareArguments( _actionExecutingContext.ActionArguments, actionMethodInfo.GetParameters());

Logger.ActionMethodExecuting(_actionExecutingContext, arguments);

var actionReturnValue = await ControllerActionExecutor.ExecuteAsync( methodExecutor, _actionExecutingContext.Controller, arguments);

var actionResult = CreateActionResult( actionMethodInfo.ReturnType, actionReturnValue);

Logger.ActionMethodExecuted(_actionExecutingContext, actionResult);

return actionResult;

Question

The methods ControllerActionExecutor.PrepareArguments and ControllerActionExecutor.ExecuteAsync are internal methods of Microsoft.AspNetCore.Mvc.Internal. I guess this will changed over time when new version of ASP.NET MVC is released. Is there any better way to invoke the action method and get IActionResult?

davidfowl commented 8 years ago

/cc @rynowak

fromberg100 commented 8 years ago

Hi skykarthick,

did you get any better ideas?

I was also looking for a solution like yours.

Are you implementing this from a middleware? If you, could you please send me a sample?

Thanks in advance and best regards, Fabian

karthicksundararajan commented 8 years ago

Hi Fabian,

Not really, unfortunately when asp.net mvc has released new version, I have to update this code completely.

I guess we need a better interface where we can call controller and get results.

Implementing from middleware would lead to re-implement most of the MVC components.

Karthick

karthicksundararajan commented 8 years ago

@davidfowl Should I ask this question in https://github.com/aspnet/mvc ?

davidfowl commented 8 years ago

Yes.