Asp.net core mvc 从ASP.NET核心中的任意URL手动实例化控制器实例

Asp.net core mvc 从ASP.NET核心中的任意URL手动实例化控制器实例,asp.net-core-mvc,Asp.net Core Mvc,我只想使用路径和正文来执行ASP.NET核心(2.1)请求。我在找这样的东西: string path = "/controller/method"; string body = "{}"; ExecuteRoute(path, body); // this calls Controller.Method(body) 目前,我通过在服务器端发出HTTP请求来实现这一点。我希望通过在没有HTTP请求的情况下执行代码,以尽可能少的开销实现这一点。我担心不必要的HTTP请求会导致高负载问题。您想实现

我只想使用路径和正文来执行ASP.NET核心(2.1)请求。我在找这样的东西:

string path = "/controller/method";
string body = "{}";
ExecuteRoute(path, body); // this calls Controller.Method(body)

目前,我通过在服务器端发出HTTP请求来实现这一点。我希望通过在没有HTTP请求的情况下执行代码,以尽可能少的开销实现这一点。我担心不必要的HTTP请求会导致高负载问题。

您想实现什么?我真的不明白你为什么这么做,我为我能想到的用例写了两个解决方案

  • 如果您希望整个请求管道都能正常工作,那么最好的方法就是您当前正在做的事情,即向localhost发出http请求。但您是对的,它比简单的方法调用需要更多的资源

  • 如果您只想在控制器中调用一个方法(控制器操作),那么您应该重新组织逻辑并创建一个可以实例化的类,一个简单的方法调用将解决您的问题


  • 你想达到什么目标?我真的不明白你为什么这么做,我为我能想到的用例写了两个解决方案

  • 如果您希望整个请求管道都能正常工作,那么最好的方法就是您当前正在做的事情,即向localhost发出http请求。但您是对的,它比简单的方法调用需要更多的资源

  • 如果您只想在控制器中调用一个方法(控制器操作),那么您应该重新组织逻辑并创建一个可以实例化的类,一个简单的方法调用将解决您的问题


  • 我一直在努力解决这个问题,最终找到了一个解决方案,这已经解释清楚了,但有一个问题我仍在努力解决

    我打电话给/3,批量请求/1和/2。所以我希望在/3次运行之前运行/1和/2,并将/3的响应返回给客户端

    发生的情况是,当代码到达/2时,我将得到错误“无法修改响应,因为它已经被发送。”。所以/first请求修改了原始请求(即/three)的响应,我再也写不出响应了

    public class BatchController : Controller
    {
        // inject this to controller via constructor
        IHttpContextFactory contextFactory;
    
        public async override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            IRouteCollection router = RouteData.Routers.OfType<IRouteCollection>().First();
    
            // run batched requets one by one
            foreach(...)
            {
                HttpContext context = contextFactory.Create(HttpContext.Features);
    
                // set request data
                context.Request.Path = path;
                context.Request.Body = body;
                context.Request.Headers = headers;
    
                var routeContext = new RouteContext(context);
                await router.RouteAsync(routeContext); // get route
                await routeContext.Handler.Invoke(context); // call controller
            }
    
            // continue
            await next();
        }
    
        [HttpGet("one")] public string One() { return "one"; }
        [HttpGet("two")] public string Two() { return "two"; }
        [HttpGet("three")] public string Three() { return "three"; }
    }
    
    公共类BatchController:控制器
    {
    //通过构造函数将其注入控制器
    IHttpContextFactory上下文工厂;
    公共异步重写任务OnActionExecutionAsync(ActionExecutionContext上下文,ActionExecutionDelegate下一步)
    {
    IRouteCollection router=RouteData.Routers.OfType().First();
    //逐个运行批处理请求
    foreach(…)
    {
    HttpContext=contextFactory.Create(HttpContext.Features);
    //设置请求数据
    context.Request.Path=路径;
    context.Request.Body=Body;
    context.Request.Headers=头;
    var routeContext=新的routeContext(上下文);
    wait router.RouteAsync(routeContext);//获取路由
    等待routeContext.Handler.Invoke(上下文);//调用控制器
    }
    //继续
    等待下一个();
    }
    [HttpGet(“one”)]公共字符串one(){返回“one”;}
    [HttpGet(“two”)]公共字符串two(){返回“two”;}
    [HttpGet(“三”)]公共字符串三({返回“三”;}
    }
    
    我试图通过将控制器方法更改为async Task(因此不需要返回)和使用response.WriteAsync手动写入响应来解决这一问题,但这会在AspNet内部代码中的某个地方出现nullreference异常,我还没有找到原因

    [16:12:50 ERR] Connection id "0HLJVLA0U0328", Request id "0HLJVLA0U0328:00000001": An unhandled exception was thrown by the application.
    System.NullReferenceException: Object reference not set to an instance of an object.
       at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.<>c__DisplayClass3_0.<OnResourceExecuting>b__0(Object state)
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FireOnStartingMayAwait(Stack`1 onStarting)
    [16:12:50 ERR] An unhandled exception has occurred while executing the request.
    System.ObjectDisposedException: The response has been aborted due to an unhandled application exception. ---> System.NullReferenceException: Object reference not set to an instance of an object.
       at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.<>c__DisplayClass3_0.<OnResourceExecuting>b__0(Object state)
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FireOnStartingMayAwait(Stack`1 onStarting)
       --- End of inner exception stack trace ---
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAbortedException()
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.InitializeResponseAsync(Int32 firstWriteByteCount)
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.WriteAsync(ReadOnlyMemory`1 data, CancellationToken cancellationToken)
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
       at Microsoft.AspNetCore.ResponseCompression.BodyWrapperStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
       at ... await Response.WriteAsync(...)
    
    [16:12:50 ERR]连接id“0HLJVLA0U0328”,请求id“0HLJVLA0U0328:00000001”:应用程序引发了未处理的异常。
    System.NullReferenceException:对象引用未设置为对象的实例。
    在Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.c__DisplayClass3_0.b__0(对象状态)中
    位于Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.fireonsttartingmayawait(堆栈'1 onStarting)
    [16:12:50错误]执行请求时发生未经处理的异常。
    System.ObjectDisposedException:由于未处理的应用程序异常,响应已中止。-->System.NullReferenceException:对象引用未设置为对象的实例。
    在Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.c__DisplayClass3_0.b__0(对象状态)中
    位于Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.fireonsttartingmayawait(堆栈'1 onStarting)
    ---内部异常堆栈跟踪的结束---
    位于Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAbortedException()上
    位于Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.httprotocol.InitializeResponseAsync(Int32 firstWriteByteCount)
    位于Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.WriteAsync(ReadOnlyMemory`1数据,CancellationToken CancellationToken)
    位于Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.WriteAsync(字节[]缓冲区,Int32偏移量,Int32计数,取消令牌取消令牌)
    位于Microsoft.AspNetCore.ResponseCompression.BodyWrapperStream.WriteAsync(字节[]缓冲区、Int32偏移量、Int32计数、CancellationToken CancellationToken)
    在等待响应。WriteAsync(…)
    
    我一直在努力解决这个问题,最终找到了一个解决方案,这已经解释过了,但有一个问题我仍在努力解决

    我打电话给/3,批量请求/1和/2。所以我希望在/3次运行之前运行/1和/2,并将/3的响应返回给客户端

    发生的情况是,当代码到达/2时,我将得到错误“无法修改响应,因为它已经被发送。”。所以/first请求修改了原始请求(即/three)的响应,我再也写不出响应了

    public class BatchController : Controller
    {
        // inject this to controller via constructor
        IHttpContextFactory contextFactory;
    
        public async override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            IRouteCollection router = RouteData.Routers.OfType<IRouteCollection>().First();
    
            // run batched requets one by one
            foreach(...)
            {
                HttpContext context = contextFactory.Create(HttpContext.Features);
    
                // set request data
                context.Request.Path = path;
                context.Request.Body = body;
                context.Request.Headers = headers;
    
                var routeContext = new RouteContext(context);
                await router.RouteAsync(routeContext); // get route
                await routeContext.Handler.Invoke(context); // call controller
            }
    
            // continue
            await next();
        }
    
        [HttpGet("one")] public string One() { return "one"; }
        [HttpGet("two")] public string Two() { return "two"; }
        [HttpGet("three")] public string Three() { return "three"; }
    }
    
    公共类BatchController:控制器
    {
    //我