tags:

views:

124

answers:

4

I want to slap a simple class together to pick out QueryString variables from an HTTP request that gets sent to my application. The variables are not always in the same order, but they're always there. I want to assign the variables in my class the values of the corresponding variables from the request, but I have no idea how to do this.

Code snippets:

MyHTTPRequest ar = new MyHTTPRequest("GET /submit.php?variableOne=value&variableTwo=someothervalue HTTP/1.1"); // Leaving out the rest for now


class MyHTTPRequest
{
    public string variableOne;
    public string variableTwo;
    public string variableThree;

    private string[] properties = { "variableOne", "variableTwo", "variableThree" }; // I know they're not actually properties

    public MyHTTPRequest(string request)
    {
        string[] variablePars = request.Substring(16, request.Length - 24).Split('&'); // variablePars now contains "variableOne=value" & "variableTwo=someothervalue"

        foreach (string variablePar in variablePars)
        {
            if (properties.Contains(variablePar.Split('=')[0])) // variableOne, variableTwo, variableThree
            {
                // Assign the correct variable the value
                <???> = variablePar.Split('=')[1]; // I don't know how to pull this one off. variablePar.Split('=')[0] should contain the name of the variable.
            }
        }
    }

}

Any input?

I'm sure a similar question already exists, but I did not know what to titel or tag this with.

+2  A: 

http://msdn.microsoft.com/en-us/library/system.web.httprequest.querystring.aspx

Steven Sudit
I use TcpClient to get the request and I'd really like to solve this my way. :-)
m3n
I got the impression that you're asking how the server can extract the querystring values from the request.
Steven Sudit
I see someone else did too (tagged it with asp.net). This is a C# application getting the packets from another program on the local machine. English is not my mother tongue and the question is probably way too fuzzy.
m3n
Why not throw out the private fields and replace them with a dictionary?
Steven Sudit
+3  A: 

You could use reflection to do this as follows:

PropertyInfo property = YourDtoClass.GetType().GetProperty("ThePropertyName");

if (property != null)
{
    property.SetValue(theTargetObject, theValue);
}

Here we first get the property of the class where your properties are defined (via reflection and the property name). If a property is found with the desired name, we then set the property value on the target object.

Or using fields instead of properties:

FieldInfo field = YourDtoClass.GetType().GetField("theFieldName");

if (field != null)
{
    field.SetValue(theTargetObject, theValue);
}

Update

This technique is only really safe (from a security perspective as others commented) if the target object that you are setting values on is purely a DTO, where all fields\properties are intended to be populated by query string values. This was the original viewpoint of my answer. If the target object contains fields that should not be set from query string values, then do not use this technique, as fields\properties that are not intended to be set from query string values, could be.

If your target object is a DTO, then the above is fine. I am assuming that this is the case.

chibacity
Right, except this breaks the moment a parameter is passed that doesn't have a corresponding property. You could patch around this by checking before setting, but I think a more general solution is to get rid of the fields and use a collection.
Steven Sudit
@Steven Wrong - that is what the "if (property != null)" is for.
chibacity
This could wind up being a security nightmare. No way should a query string have the impact of directly setting class parameters.
drharris
@drharris I think your comment belongs as a comment to the question, rather than a comment to my answer.
chibacity
No, I was specifically talking about using reflection to directly set the parameters. The question itself is valid, and other answers to it are providing much better solutions than reflection.
drharris
As drharris pointed out, checking for a valid parameter is going to require more than just a null check.
Steven Sudit
@drharris I see your point. I was answering from the viewpoint that the OP was just cramming data into a DTO.
chibacity
+4  A: 

Use the System.Web.HttpUtilityClass.ParseQueryString. It returns a NameValueCollection just like you get in ASP.NET with Request.QueryString.

// assuming you can parse your string to get your string to this format.
string queryStringText = "variableOne=value&variableTwo=someothervalue";

NameValueCollection queryString = 
     HttpUtility.ParseQueryString(queryStringText);

string variable1 = queryString["variableOne"];
string variable2 = queryString["variableTwo"];
btlog
Using this class to do the parsing is a nice detail, but the real issue here is how to map the querystring values to the class. The OP is pushing towards something reflection-based, while I'm warning against it.
Steven Sudit
Does this not answer the assigning of variables. If the query string variable names are know, but the order isn't then this resolves that as the name of parameter is used to retrieve it. In my code example variable1 will always be assigned to the parameter variableOne regardless of the order of the parameter in the query string.
btlog
If we already have the values in the collection, why do we need to additionally copy them into fields?
Steven Sudit
This was an example. I don't know how this is to be used. There are reasons why not just using the collection may be better, but it is dependent on how the class and data gets used.
btlog
There may be, but no indication was given of them.
Steven Sudit
+3  A: 

Why not turn it around?

class MyHTTPRequest {
  public string variableOne { get { return _values["variableOne"]; } }
  public string variableTwo { get { return _values["variableTwo"]; } }
  public string variableThree { get { return _values["variableThree"]; } }
  NameValueCollection _values;
  public MyHTTPRequest(string queryStringText) { 
    _values = HttpUtility.ParseQueryString(queryStringText); 
  }
} 
Jordão
I'll go with this approach. Thanks guys
m3n