首页 > 解决方案 > 在 .net core webapi 中访问 QueryString、Route 参数值

问题描述

我有一个独特的情况,我需要从[FromRoute]or[FromQuery]或获取 DepartmentId [FromBody]。这很奇怪,因为我不能破坏我的公共 api 操作合同,也不能做太多事情。此外,我无法更改从控制器内部调用的业务合同,因此我无法将 DepartmentId 传递到管道中。

我看到我可以注入IHttpContextAccessor并获得IHttpContextAccessor.HttpContext. 我能够获得如下的 DepartmentId [FromQuery]

request.QueryString.Value.Replace("?", "")
                            .Split("&")
                            .FirstOrDefault(x => x.Contains("departmentId"))
                            ?.Split("=")[1];

我得到它[FromRoute]的参数如下;

var departmentId = 0;
var match = Regex.Match(request.Path, "Department/\\d+");
if (match.Success && match.Groups.Any())
{
    int.TryParse(match.Groups[0].Value.Replace("Department/", ""), out departmentId);
} 

我不知道如何从[FromBody]复杂对象中获取 DepartmentId。但我确实知道在 中使用的所有请求对象[HttpPost]都是从Department具有DepartmentId.

任何帮助表示赞赏....

标签: c#asp.net-core-2.0asp.net-core-webapi

解决方案


使用中间件我会做这样的事情:

public class EstablishDepartmentMiddleware
{
    private RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context, IDepartmentContext departmentContext)
    {            
        await TryGetDepartmentFromBody(context, departmentContext);
        // TryGetFromQuery
        // TryGetFromRoute
        await _next(context);
    }

    private static async Task TryGetDepartmentFromBody(HttpContext context, IDepartmentContext departmentContext)
    {
        using (var sr = new StreamReader(context.Request.Body))
        {
            var bodyText = await sr.ReadToEndAsync();
            var department = JsonConvert.DeserializeObject<Department>(bodyText);
            if (department != null)
            {
                departmentContext.DepartmentId = department.DepartmentId;
            }
        }
    }
}

以下是其他类:

public interface IDepartmentContext
{
    int DepartmentId { get; set; }
}

public class DepartmentContext : IDepartmentContext
{
    public int DepartmentId { get; set; }
}

public class Department
{
    public int DepartmentId { get; set; }
}

以下是启动类的内容:

app.UseMiddleware<EstablishDepartmentMiddleware>();

你也可以对动作过滤器做类似的事情——中间件将处理所有到达的请求。

显然,您可以使用上面的代码并使用 IHttpContextAccessor 从 Body 获取 DepartmentId 的相同方式。请记住 - 如果您在业务类中使用访问器,您可能会将基础架构泄漏到业务层。


推荐阅读