16

I am using Web API and have setup a simple authentication and authorization mechanism where the caller passes a token that I have issued to them in the query string. So they submit a request like:

https://mysite.com/api/Ping?token=[issued-token]

I have an ApiAuthorizeAttribute like this:

public class ApiAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
    public ApiPermission Permission { get; set; }

    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        switch (Permission)
        {
            case ApiPermission.None: 
               return;

           case ApiPermission.Write:
           case ApiPermission.Read:

               string query = actionContext.Request.RequestUri.Query;
               var nvc = System.Web.HttpUtility.ParseQueryString(query);
               string token = nvc["token"];

               // (my code to map the token to an Authorization for the request)               
               ApiAuthorization auth = ApiToken.GetAuthorization(token);
               if (auth != null && auth.HasPermission(Permission))
                   return;

               HandleUnauthorizedRequest(actionContext);
               return;

           default:
               throw new ArgumentException("Unexpected Permission");
        }
    }
}

Then I can decorate my APIs like this. Note: this is just an example, a real call would read data from their account (an account identifier is encrypted within their token) and return it.

/// <summary>
/// Ping service that requires a Token with Read permission
/// Returns "Success!"
/// </summary>
[ApiAuthorize(Permission = ApiPermission.Read)]
[HttpGet]
public string Ping()
{
    return "Success!";
}

As you might note, I could not access the QueryString anywhere from HttpActionContext parameter and had to build it myself. It seems like they explicitly removed QueryString from this Request object. I don’t want to add “token” it to each and every API method in order to get it in the Route Data.

So my questions are:

  1. Is the QueryString in there somewhere and I am just missing it? If not, any idea why Microsoft doesn't include it with this Request object? (i.e. maybe this is a bad thing to do?)
  2. Is there a better way to deal with getting the token in the AuthorizeAttribute (again, without adding it to each call)?

BTW, I realize there are other (probably better) options for authorization such as Basic Authentication and OAuth, and I do not want to debate that topic here.

3
  • Have you tried actionContext.Request.QueryString. stackoverflow.com/questions/2219647/… Commented May 29, 2013 at 5:29
  • @Satpal, yes I had assumed that property would be there when I started writing my code. But that particular Request object does not have that property. That is the crux of my question - why not? Commented May 29, 2013 at 5:32
  • actionContext.Request.RequestUri.Query may also be useful. http://stackoverflow.com/questions/12817202/accessing-post-or-get... Commented May 14, 2014 at 2:43

3 Answers 3

38

While Adam Tal's answer is perfectly valid, in the Web API new world order you really do not want to use anything from the System.Web namespace; in fact you don't even want to reference it. Alas you can get to the querystring from the GetQueryNameValuePairs() extension method. That will let you cut System.Web boat anchor loose and still get to what you need.

using System.Net.Http;

var queryString = actionContext.Request
        .GetQueryNameValuePairs()
        .ToDictionary(x => x.Key, x => x.Value);
Sign up to request clarification or add additional context in comments.

2 Comments

Just to add (because it took me a second to find it), you can find this extension method by using the System.Net.Http namespace.
Completely right. Especially if someone wants to work with vnext and get rid of System.Web. You've got my upvote :)
12

Try

using System.Web;

HttpContext.Current.Request.QueryString

7 Comments

Yes, that works. It was a rather long-winded question for such a such a straightforward answer... But I am still left wondering why it is not in their Request object - it is leaving me with the feeling that maybe I shouldn't be grabbing parameters off the query string in the AuthorizeAttribute.
any ideas how to access post request
@jaminator - Try using HttpContext.Current.Request.Form dictionary which contains the post data instead of the QueryString which takes the data from the url.
@AdamTal data is passed to me in json post request
@jaminator - did you try what I've suggested?
|
1
NameValueCollection queryString = actionContext.Request.RequestUri.ParseQueryString();

It works for me.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.