【问题标题】:Is it possile to return .NET object from controller to middleware是否可以将 .NET 对象从控制器返回到中间件
【发布时间】:2022-01-10 14:17:25
【问题描述】:

我正在处理其中一个需求,我需要修改中间件中的结果数据(不是任何 MVC 过滤器,因为通过中间件注入了一些其他服务)。

在中间件中,我获取 json 格式的数据,然后反序列化该数据,然后更新该数据,最后序列化为 JSON 并将其作为响应发送回。

我不想在 MVC 管道中序列化数据,所以我尝试删除输出格式化程序,但这对我不起作用并引发错误。

services.AddControllers(options =>
        {
            options.OutputFormatters.Clear();
        });

是否有任何解决方案可以在管道中获取 .Net 对象并修改该对象(就像我们在 MVC 过滤器中所做的那样),然后最后进行序列化?

【问题讨论】:

  • 你能提供你想做的伪代码吗?我有点困惑。您是要修改返回的ActionResult(我认为只有 Action Filter 可以这样做,因为中间件没有 ActionResult 的概念)、响应或其他什么?
  • 你检查Result filters了吗?
  • @LukeVo 我使用soapcore nuget 包将我的服务公开为带有REST 的SOAP。如果我要修改结果过滤器中的结果,它将适用于 REST 请求,因为 SOAPCORE 与 mvc 管道分开,我不想在 2 个地方编写我的业务逻辑(用于结果过滤器中的 REST 请求和中间件中的 SOAP) .
  • 我明白了。那么是的,您将需要使用HttpContext.Items,或范围服务。

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


【解决方案1】:

我不确定它是否符合您的要求,但您可以使用 HttpContext 在请求范围内存储一些数据。有一个“项目”键值集合。

【讨论】:

  • 欢迎来到 StackOverflow。你的答案很好,但如果你能提供一些示例代码会更好:)
【解决方案2】:

除了使用HttpContext 中的Items 的其他建议之外,我想指出您可以将服务注入操作过滤器:

public class ResultFilter : IActionFilter
{

    // Inject anything you want
    IHostEnvironment env;
    public ResultFilter(IHostEnvironment env)
    {
        this.env = env;
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        if (context.Result is OkObjectResult result)
        {
            result.Value = JsonSerializer.Serialize(new
            {
                Value = result.Value,
                Environment = this.env.EnvironmentName,
            });
        }
    }

    public void OnActionExecuting(ActionExecutingContext context) { }
}

注册到 DI Builder:

services.AddScoped<ResultFilter>();

应用于动作/控制器:

    [HttpGet, Route("/test"), ServiceFilter(typeof(ResultFilter))]
    public IActionResult ReturnOk()
    {
        return this.Ok(new
        {
            Value = 1,
        });
    }

通过访问 URL 进行测试:

{"Value":{"Value":1},"Environment":"Development"}

【讨论】:

    【解决方案3】:

    另一种选择是使用带有Scoped lifetime 的DI 服务。

    作用域对象对于给定的请求是相同的,但在每个新请求中是不同的。

    服务:

    public interface IMyRequestDataService
    {
        object? MyData { get; set; }
    }
    
    public class MyRequestDataService : IMyRequestDataService
    {
    
        public object? MyData { get; set; }
    
    }
    

    向 DI 注册:

    services.AddScoped<IMyRequestDataService, MyRequestDataService>();
    

    在Controller中设置数据:

        readonly IMyRequestDataService dataService;
        public TestController(IMyRequestDataService dataService)
        {
            this.dataService = dataService;
        }
    
        [HttpGet, Route("/test-scoped")]
        public IActionResult ReturnObj()
        {
            this.dataService.MyData = new
            {
                Value = 1,
            };
    
            return this.Ok();
        }
    

    使用它的中间件:

    class CustomMiddleware
    {
        readonly RequestDelegate next;
        public CustomMiddleware(RequestDelegate next)
        {
            this.next = next;
        }
    
        // Add DI Services here
        public async Task InvokeAsync(HttpContext httpContext, IMyRequestDataService dataService, IHostEnvironment env)
        {
            await this.next(httpContext);
    
            // Data should be here
            if (dataService.MyData != null)
            {
                // Do something with it
                await httpContext.Response.WriteAsJsonAsync(new
                {
                    Data = dataService.MyData,
                    Env = env.EnvironmentName,
                });
            }
        }
    
    }
    
    // Register it:
    app.UseMiddleware<CustomMiddleware>();
    
    // Make sure it's before the Controller middleware since we wrap it around the next()
    // ...
    
    app.MapControllers();
    

    用 URL 测试:

    {"data":{"value":1},"env":"Development"}
    

    【讨论】:

      【解决方案4】:

      您可以将数据存储在 HTTP 上下文项中。

      在控制器动作中:

      Request.HttpContext.Items.Add("SomeKey", data);
      

      在中间件中:

      object data = httpContext.Items["SomeKey"];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-05
        • 1970-01-01
        • 2018-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多