Web API 2.2, Is there an easy way to update the HttpRequestMessage's QueryString in a DelegatingHandler?

时间:2015-06-15 15:02:49

标签: c# query-string asp.net-web-api2

I've created a custom MessageHandler as such:

public class WebAPICustomMessageHandler : DelegatingHandler {

  protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
  //Parse QueryString
    NameValueCollection queryString = HttpUtility.ParseQueryString(request.RequestUri.Query);

    if (queryString != null) {
    //Find my token
      String token = queryString.Get("qsVariable");

      if (!String.IsNullOrWhiteSpace(token)) {
      //Remove token so it doesn't impact future handlers / controllers / etc.
        queryString.Remove("qsVariable");
        request.RequestUri.Query = queryString.ToString(); //How can we modify the querystring? apparently it's readonly?

      //Append token as custom header to the request
        request.Headers.Add("token", new String[] { token });
      }
    }

    HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

    return response;
  }

}

It appears that I can't directly change the QueryString, which is a bit odd as I thought that the entire point of custom message handlers in the Web API pipeline was to allow this exact sort of thing. The ability issue pre and post operations on request/response, including things like data scrubbing / injection etc.

I already know I can do what I want very easily utilizing OWIN (as I've already done it), but now I'm trying to do this without OWIN. Am I going to have to create an entirely new HttpRequestMessage in order to just change the QueryString? From the looks of it, I'll have to build a new Uri, then construct the HttpRequestMessage, then copy over each and every other piece from the original.

Is that the only way to do this? or is there a better way that I'm just not aware of?

  • Please note, that other routines later in the pipeline are setup to use a token found in the header of the request, but setting the header is not possible if the request came from a submission to an iframe, which is where the process above comes into place. The token is added to the querystring, then converted to a header to prevent changes to the rest of the pipeline.

1 个答案:

答案 0 :(得分:0)

你是对的,查询字符串是只读的。只需使用带有替换查询字符串值的标准重定向。

public class WebAPICustomMessageHandler : DelegatingHandler {

  protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
    var query = HttpUtility.ParseQueryString(request.RequestUri.Query);
    var token = query["qsVariable"];

    // just 'short-circuit' if our token was not found...
    if (token == null) 
      return await base.SendAsync(request, cancellationToken);

    token = "newValue"; // modify your value here...
    query["token"] = token;

    // redirect with new query string...
    var response = request.CreateResponse(HttpStatusCode.Redirect);
    var uri = request.RequestUri;
    var ub = new UriBuilder(uri.Scheme,
      uri.Host,
      uri.Port,
      uri.AbsolutePath);
    ub.Query = query.ToString();
    response.Headers.Location = ub.Uri;
    return response;
  }
}

为了感兴趣,即使它是只读的,也可以modify the query string,但我会避免这种做法。