ASP.NET Web API 中的参数绑定

本文关键字:参数 绑定 API NET Web ASP | 更新日期: 2023-09-27 18:32:10

我的Web API中有一个用于身份验证(HMAC)的DelegatingHandler。

我想在请求中添加一个 GET 参数,以将用户的 id 返回给我的控制器。

在我的处理程序中,我尝试像这样添加它:

public class SecurityHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        string apikey = request.Headers.GetValues(AuthConfig.ApiKeyHeader).First();
        UserDTO user = UserRepo.GetUser(apikey);
        if (user == null)
        {
            return SendResponseText("Invalid API key");
        }
        // Validate signature ...
        // Add user Id to the URI
        request.RequestUri = new Uri(request.RequestUri.OriginalString + "&UserId=" + user.Id);
        return base.SendAsync(request, cancellationToken);
    }
}

在我的控制器中,我能够从请求 uri 中获取新添加的参数,但是参数绑定不起作用

public class MyModel
{
    public int UserId { get; set; }
    ...
}
public string Get([FromUri] MyModel model)
{
    // model.UserId has not been set (= 0)
    // Request.RequestUri contains "&UserId=5"
}

更新

我猜绑定是从 HttpContext 中的参数完成的。我尝试过这样的东西,但 Params 集合是只读的。

var newContext = request.Properties["MS_HttpContext"] as HttpContextWrapper;
newContext.Request.Params.Add("UserId", "8");
request.Properties.Remove("MS_HttpContext");
request.Properties.Add("MS_HttpContext", newContext);

ASP.NET Web API 中的参数绑定

我已经在我身边尝试过并且它有效。

这是我的示例网址。

http://localhost:50382/api/values?UserId=10

下面是控制器操作。

public class ValueController : ApiController
{
    public IEnumerable<string> Get([FromUri]Model my)
            {
                return new string[] { "value1", "value2" , my.UserId.ToString() };
            }
}

根据您在此处的评论,我创建了委托处理程序。

  public class MyMessageHandler : DelegatingHandler
  {
    protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var myTempObj = new { id = 20 };
      /* You have to check this and remove this key. If key present that FromUri use cached properties*/
        if (request.Properties.ContainsKey("MS_QueryNameValuePairs"))
        {
            request.Properties.Remove("MS_QueryNameValuePairs");                
        }
        // Now prepare or update uri over here. It will surely work now.
            if (!string.IsNullOrEmpty(request.RequestUri.Query) && request.RequestUri.Query.Contains('?'))
            {
                request.RequestUri = new Uri(request.RequestUri + "&UserID=" + myTempObj.id);
            }
            else
            {
                request.RequestUri = new Uri(request.RequestUri + "?UserID=" + myTempObj.id);
            }    
        return base.SendAsync(request, cancellationToken);
    }
}

这是按预期工作。

如果您的原始请求包含 userid,那么它会重复并且无法正常工作。它返回 0。

我也怀疑你是否在使用请求。RequestUri.OriginalString. 只需尝试使用请求。请求里。OriginalString 可能具有编码值。

我找到了以下解决问题的方法

request.RequestUri = new Uri(request.RequestUri + "&UserId=8");
var newFormDataCollection = new FormDataCollection(request.RequestUri);
request.Properties.Remove("MS_QueryNameValuePairs");
request.Properties.Add("MS_QueryNameValuePairs", newFormDataCollection);
return base.SendAsync(request, cancellationToken);

[FromURI]似乎使用 FormDataCollection 中的值,因此您只需更新"MS_QueryNameValuePairs"属性。