HttpRequest.RouteValues属性在代码中不可访问,但可从调试器中访问。

huangapple go评论79阅读模式
英文:

HttpRequest.RouteValues property is not accessible from code but accessible from debugger

问题

我正在尝试创建一个中间件,用于对特定请求执行一些检查。

例如,我有以下路由:

  • api/Test/{paramToCheck}/aaa
  • api/Test/bbb/ccc

以及这些请求:

  • http://some-host-and-port/api/Test/1234/aaa
  • http://some-host-and-port/api/Test/bbb/ccc

现在,在我的中间件中,我想要检查请求是否包含 {paramToCheck},并获取此参数的值。

当我在 InvokeAsync 中设置断点时,我可以看到 httpContext.Request.RouteValues 属性包含所有所需的数据(Keys 包含 "paramToCheck"Values 包含其值)。

但在代码中,我无法访问此属性,我收到错误消息:

错误 CS1061:'HttpRequest' 不包含对 'RouteValues' 的定义,也找不到可访问的扩展方法 'RouteValues',接受 'HttpRequest' 类型的第一个参数(是否缺少 using 指令或程序集引用?)

var value = httpContext.Request.RouteValues["paramToCheck"]; // 此处出错

我如何访问此属性或执行所需的检查?

代码:

public class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next)
    {
        this._next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        var value = httpContext.Request.RouteValues["paramToCheck"]; // 此处出错

        //... 一些与值相关的逻辑

        await this._next(httpContext);
    }
}

编辑

中间件位于 netstandard2.1 类库中,不能移到 api 项目中,因为它是通用的,应该被多个 api 项目使用。

更新

目前似乎无法实现,因为 RouteValues 属性是在 Microsoft.AspNetCore.Http.Abstractions 3.0.0 中添加的,该包含在 NetCoreApp 3 元包中。而在 netstandard 2.1 项目中无法安装此包,因为最新版本是 2.2.0

英文:

I am trying to create middleware which performs some checking for particular requests.

For example, I have such routes:

  • api/Test/{paramToCheck}/aaa
  • api/Test/bbb/ccc

and I have these requests:

  • http://some-host-and-port/api/Test/1234/aaa
  • http://some-host-and-port/api/Test/bbb/ccc

Now inside my middleware I want to check if request contains {paramToCheck} and get value of this parameter.

When I set breakpoint inside InvokeAsync I can see httpContext.Request.RouteValues property containing all needed data (Keys contains "paramToCheck" and Values contains its value).

But in code I can't access this property, I get error:

> Error CS1061: 'HttpRequest' does not contain a definition for
> 'RouteValues' and no accessible extension method 'RouteValues'
> accepting a first argument of type 'HttpRequest' could be found (are
> you missing a using directive or an assembly reference?)

var value = httpContext.Request.RouteValues["paramToCheck"];

How can I access this property or how can I perform needed check?

Code:

public class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware
    (
        RequestDelegate next
    ) => this._next = next;

    public async Task InvokeAsync(HttpContext httpContext)
    {
        var value = httpContext.Request.RouteValues["paramToCheck"]; // error here
        
        //... some logis with value

        await this._next(httpContext);
    }
}

EDIT

Middleware is inside netstandard2.1 class library and it cannot be moved to api project as it is common and should be used by several api projects.

UPDATE

Seems like currently it cannot be achieved as RouteValues propery was added in Microsoft.AspNetCore.Http.Abstractions 3.0.0 which is inside NetCoreApp 3 metapackage. And there is no possibility to install this package in netstandard 2.1 project because the latest version is 2.2.0.

答案1

得分: 7

使用一个类库,对我来说升级到使用.NET Core 3.1的Microsoft.AspNetCore.App而不是Microsoft.AspNetCore.Http.Abstractions v2.2是答案。

这里所述,.NET Core 3取消了所有小型包,所以我替换了:

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
</ItemGroup>

改为:

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App"/>
</ItemGroup>

然后我可以这样访问路由:

HttpContext.Request.RouteValues["version"];

其中{version} 在路由中设置。

英文:

Using a class library, the answer for me was to upgrade to using .netcore 3.1's Microsoft.AspNetCore.App instead of Microsoft.AspNetCore.Http.Abstractions v2.2

As stated here, .net core 3 did away with all the small packages, so I replaced

&lt;PropertyGroup&gt;
    &lt;TargetFramework&gt;netcoreapp3.1&lt;/TargetFramework&gt;
  &lt;/PropertyGroup&gt;

  &lt;ItemGroup&gt;
    &lt;PackageReference Include=&quot;Microsoft.AspNetCore.Http.Abstractions&quot; Version=&quot;2.2.0&quot; /&gt;
  &lt;/ItemGroup&gt;

with

&lt;PropertyGroup&gt;
    &lt;TargetFramework&gt;netcoreapp3.1&lt;/TargetFramework&gt;
  &lt;/PropertyGroup&gt;

  &lt;ItemGroup&gt;
	  &lt;FrameworkReference Include=&quot;Microsoft.AspNetCore.App&quot;/&gt;
  &lt;/ItemGroup&gt;

and then I could access the route like so:

HttpContext.Request.RouteValues[&quot;version&quot;];

where {version} was set in the route.

答案2

得分: 6

今天遇到了同样的问题。

这是一个巧妙的解决方法,但它有效。

IReadOnlyDictionary<string, object>? routeValues = ((dynamic)context.Request).RouteValues as IReadOnlyDictionary<string, object>;
英文:

Just encountered the same problem today.

This is hacky but it works

IReadOnlyDictionary&lt;string, object&gt;? routeValues = ((dynamic)context.Request).RouteValues as IReadOnlyDictionary&lt;string, object&gt;;

答案3

得分: 2

听起来你正在尝试从一个没有访问 httpContext 权限的服务实现中访问这个内容,我说得对吗?要将它放在你的 API 项目之外。

如果你在控制器中执行 httpContext.Request.RouteValues["paramToCheck"];,它是否起作用... 然后要让它起作用,可以在控制器中执行这个操作,然后将结果传递给库。

httpContext 与 BaseController 或 ControllerBase 有“绑定”关系... 无论如何它被调用... 基本上你期望的连接没有在你的库中完成... 所以 httpContext 完全没有 web 上下文,有一种更好的方式来表达这一点... 所有这些,但你明白了。

英文:

sounds like you trying to access this from a service implementation which does not have access to httpContext, am i correct in saying to have this outside of your api project.

if you do httpContext.Request.RouteValues[&quot;paramToCheck&quot;]; in controller does it works... then to get it to work , do this in controller and pass the result to the lib.

httpContext has "binding"* to BaseController or ControllerBase... what ever its call.. basically the wiring which you are expecting is not done in your lib... so httpContext has no web context at all, there is a much better way to word this... all, but you get the just.

答案4

得分: 2

你可以使用扩展方法.GetRouteData()来自RoutingHttpContextExtensions,它会提供一个RouteData实例。这个扩展方法是Microsoft.AspNetCore.Routing包的一部分。

RouteData 包含一个名为 Values 的类型为 RouteValueDictionary 的属性成员。

var routeData = httpContext.GetRouteData();

if (routeData.Values.TryGetValue("paramToCheck", out object value))
{
    // ... 对该值进行一些逻辑处理
}

要更深入了解 RoutingHttpContextExtensionsRouteData,请查看源代码,链接如下:
https://github.com/dotnet/aspnetcore/tree/3.0/src/Http/Routing

英文:

You can use the extension .GetRouteData() from RoutingHttpContextExtensions which will provide you a RouteData instance. This extension is part of Microsoft.AspNetCore.Routing package.

The RouteData contains a property member of type RouteValueDictionary called Values.

var routeData = httpContext.GetRouteData();

if (routeData.Values.TryGetValue(&quot;paramToCheck&quot;, out object value))
{
    // ... Do some logic with the value
}

To understand a bit more about the RoutingHttpContextExtensions and RouteData check the source code at
https://github.com/dotnet/aspnetcore/tree/3.0/src/Http/Routing

答案5

得分: 0

Alexander Ivanov 的回答:

routeValues = ((dynamic)context.Request).RouteValues as IReadOnlyDictionary<string, object>;

对我有用,谢谢!不过,要让它起作用,我花了一点时间,因为需要以下包:

  • Microsoft.AspNetCore.Http.Abstractions
  • Microsoft.CSharp

希望这些额外信息能帮助别人节省一些时间。

英文:

Alexander Ivanov's answer:

routeValues = ((dynamic)context.Request).RouteValues as IReadOnlyDictionary&lt;string, object&gt;;

worked for me, thanks! It took me a little to get it working, however, as the following packages were required:

  • Microsoft.AspNetCore.Http.Abstractions
  • Microsoft.CSharp

Including this additional information in the hopes it saves someone some time.

huangapple
  • 本文由 发表于 2020年1月6日 18:32:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/59610509.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定