Convert querystring from/to object

2019-01-17 20:39发布

问题:

I have this (simplified) class:

public class StarBuildParams
{
    public int BaseNo { get; set; }
    public int Width { get; set; }
}

And I have to transform instances of it to a querystring like this:

"BaseNo=5&Width=100"

Additionally I have to transform such a querystring back in an object of that class.

I know that this is pretty much what a modelbinder does, but I don't have the controller context in my situation (some deep buried class running in a thread).

So, is there a simple way to convert a object in a query string and back without having a controller context?

It would be great to use the modelbinding but I don't know how.

回答1:

You can use reflection, something like this:

public T GetFromQueryString<T>() where T : new(){
    var obj = new T();
    var properties = typeof(T).GetProperties();
    foreach(var property in properties){
        var valueAsString = HttpContext.Current.Request.QueryString[property.PropertyName];
        var value = Parse( valueAsString, property.PropertyType);

        if(value == null)
            continue;

        property.SetValue(obj, value, null);
    }
    return obj;
 }

You'll need to implement the Parse method, just using int.Parse, decimal.Parse, DateTime.Parse, etc.



回答2:

Use this Parse method with the ivowiblo's solution (accepted answer):

public object Parse(string valueToConvert, Type dataType)
{
    TypeConverter obj = TypeDescriptor.GetConverter(dataType);
    object value = obj.ConvertFromString(null, CultureInfo.InvariantCulture,  valueToConvert);
    return value;
}


回答3:

A solution with Newtonsoft Json serializer and linq:

string responseString = "BaseNo=5&Width=100";
var dict = HttpUtility.ParseQueryString(responseString);
string json = JsonConvert.SerializeObject(dict.Cast<string>().ToDictionary(k => k, v => dict[v]));
StarBuildParams respObj = JsonConvert.DeserializeObject<StarBuildParams>(json);


回答4:

You can set the properties of this object in its constructor by retrieving the relevant values from the querystring

public StarBuildParams()
{
    this.BaseNo = Int32.Parse(Request.QueryString["BaseNo"].ToString());
    this.Width = Int32.Parse(Request.QueryString["Width"].ToString());
}

and you can ensure that the object is converted to the correct querystring format by overriding the ToString method.

public override string ToString()
{
    return String.Format("BaseNo={0}&Width={1}", this.BaseNo, this.Width);
}

You'll still need to construct and call ToString in the appropriate places, but this should help.



回答5:

This should work so long as none of the properties match any other route parameters like controller, action, id, etc.

new RouteValueDictionary(Model)

http://msdn.microsoft.com/en-us/library/cc680272.aspx

Initializes a new instance of the RouteValueDictionary class and adds values that are based on properties from the specified object.

To parse back from the query string you can use the model class as an action parameter and let the ModelBinder do it's job.



回答6:

You can just use .NET's HttpUtility.ParseQueryString() method:

HttpUtility.ParseQueryString("a=b&c=d") produces a NameValueCollection as such:

[0] Key = "a", Value = "b"
[1] Key = "c", Value = "d"