C# 将查询字符串从/转换为对象

C# 将查询字符串从/转换为对象,c#,asp.net-mvc-3,C#,Asp.net Mvc 3,我有这个(简化的)课程: 我必须将它的实例转换为如下查询字符串: "BaseNo=5&Width=100" public T GetFromQueryString<T>() where T : new(){ var obj = new T(); var properties = typeof(T).GetProperties(); foreach(var property in properties){ var valueAsStri

我有这个(简化的)课程:

我必须将它的实例转换为如下查询字符串:

"BaseNo=5&Width=100"
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;
 }
此外,我还必须将此类查询字符串转换回该类的对象中

我知道这几乎就是modelbinder所做的,但在我的情况下,我没有控制器上下文(一些深埋的类在线程中运行)

那么,有没有一种简单的方法可以在没有控制器上下文的情况下转换查询字符串中的对象并返回


使用modelbinding很好,但我不知道如何使用。

您可以通过从querystring中检索相关值,在其构造函数中设置此对象的属性

public StarBuildParams()
{
    this.BaseNo = Int32.Parse(Request.QueryString["BaseNo"].ToString());
    this.Width = Int32.Parse(Request.QueryString["Width"].ToString());
}
您可以通过重写
ToString
方法来确保将对象转换为正确的querystring格式

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

您仍然需要在适当的位置构造并调用
ToString
,但这应该会有所帮助。

您可以使用反射,类似于以下内容:

"BaseNo=5&Width=100"
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;
 }
public T GetFromQueryString(),其中T:new(){
var obj=新的T();
var properties=typeof(T).GetProperties();
foreach(属性中的var属性){
var valueAsString=HttpContext.Current.Request.QueryString[property.PropertyName];
var value=Parse(valueAsString,property.PropertyType);
如果(值==null)
继续;
SetValue(obj,value,null);
}
返回obj;
}

您需要实现Parse方法,只需使用int.Parse、decimal.Parse、DateTime.Parse等。

只要属性与任何其他路由参数(如控制器、操作、id等)都不匹配,就可以使用该方法

new RouteValueDictionary(Model)

初始化RouteValueDictionary类的新实例并添加 基于指定对象的属性的值


要从查询字符串解析回来,您可以使用模型类作为操作参数,并让ModelBinder完成它的工作。

将此解析方法与ivowiblo的解决方案(接受的答案)一起使用:


您只需使用.NET的
HttpUtility.ParseQueryString()
方法:

HttpUtility.ParseQueryString(“a=b&c=d”)
生成一个
NameValueCollection
,如下所示:

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

使用Newtonsoft Json序列化程序和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);
string responseString=“BaseNo=5&Width=100”;
var dict=HttpUtility.ParseQueryString(responseString);
字符串json=JsonConvert.SerializeObject(dict.Cast().ToDictionary(k=>k,v=>dict[v]);
StarBuildParams respObj=JsonConvert.DeserializeObject(json);

基于以上Ivo和Anupam Singh的伟大解决方案,下面是我用来将其转换为POST请求基类的代码(如果您可能只有原始查询字符串,就像在Web API设置中一样)。这段代码适用于对象列表,但可以很容易地修改为解析单个对象

public class PostOBjectBase
{
        /// <summary>
        /// Returns a List of List<string> - one for each object that is going to be parsed.
        /// </summary>
        /// <param name="entryListString">Raw query string</param>
        /// <param name="firstPropertyNameOfObjectToParseTo">The first property name of the object that is sent in the list (unless otherwise specified).  Used as a key to start a new object string list.  Ex: "id", etc.</param>
        /// <returns></returns>
        public List<List<string>> GetQueryObjectsAsStringLists(string entryListString, string firstPropertyNameOfObjectToParseTo = null)
        {
            // Decode the query string (if necessary)
            string raw = System.Net.WebUtility.UrlDecode(entryListString);

            // Split the raw query string into it's data types and values
            string[] entriesRaw = raw.Split('&');

            // Set the first property name if it is not provided
            if (firstPropertyNameOfObjectToParseTo == null)
                firstPropertyNameOfObjectToParseTo = entriesRaw[0].Split("=").First();

            // Create a list from the raw query array (more easily manipulable) for me at least
            List<string> rawList = new List<string>(entriesRaw);

            // Initialize List of string lists to return - one list = one object
            List<List<string>> entriesList = new List<List<string>>();

            // Initialize List for current item to be added to in foreach loop
            bool isFirstItem = false;
            List<string> currentItem = new List<string>();

            // Iterate through each item keying off of the firstPropertyName of the object we will ultimately parse to
            foreach (string entry in rawList)
            {
                if (entry.Contains(firstPropertyNameOfObjectToParseTo + "="))
                {
                    // The first item needs to be noted in the beginning and not added to the list since it is not complete
                    if (isFirstItem == false)
                    {
                        isFirstItem = true;
                    }
                    // Finished getting the first object - we're on the next ones in the list
                    else
                    {
                        entriesList.Add(currentItem);
                        currentItem = new List<string>();
                    }
                }
                currentItem.Add(entry);
            }

            // Add the last current item since we could not in the foreach loop
            entriesList.Add(currentItem);

            return entriesList;
        }

        public T GetFromQueryString<T>(List<string> queryObject) where T : new()
        {
            var obj = new T();
            var properties = typeof(T).GetProperties();
            foreach (string entry in queryObject)
            {
                string[] entryData = entry.Split("=");
                foreach (var property in properties)
                {
                    if (entryData[0].Contains(property.Name))
                    {
                        var value = Parse(entryData[1], property.PropertyType);

                        if (value == null)
                            continue;

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

        public object Parse(string valueToConvert, Type dataType)
        {
            if (valueToConvert == "undefined" || valueToConvert == "null")
                valueToConvert = null;
            TypeConverter obj = TypeDescriptor.GetConverter(dataType);
            object value = obj.ConvertFromString(null, CultureInfo.InvariantCulture, valueToConvert);
            return value;
        }
}
公共类PostOBjectBase
{
/// 
///返回列表的列表-每个要分析的对象对应一个列表。
/// 
///原始查询字符串
///列表中发送的对象的第一个属性名(除非另有规定)。用作启动新对象字符串列表的键。例如:“id”等。
/// 
公共列表GetQueryObjectsAsStringList(string entryListString,string firstPropertyNameOfObjectToParseTo=null)
{
//解码查询字符串(如有必要)
string raw=System.Net.WebUtility.UrlDecode(entryListString);
//将原始查询字符串拆分为其数据类型和值
字符串[]entriesRaw=raw.Split('&');
//设置第一个属性名(如果未提供)
if(firstPropertyNameOfObject ToParseTo==null)
firstPropertyNameOfObjectToParseTo=entriesRaw[0]。拆分(“=”).First();
//至少为我从原始查询数组(更容易操作)创建一个列表
列表原始列表=新列表(entriesRaw);
//初始化要返回的字符串列表列表-一个列表=一个对象
List entriesList=新列表();
//初始化要添加到foreach循环中的当前项的列表
bool isFirstItem=false;
List currentItem=新列表();
//迭代通过键入我们最终将解析到的对象的firstPropertyName的每个项
foreach(原始列表中的字符串条目)
{
if(entry.Contains(firstPropertyNameOfObjectToParseTo+“=”))
{
//第一项需要在开头注明,因为它不完整,所以不能添加到列表中
if(isFirstItem==false)
{
isFirstItem=true;
}
//获取完第一个对象-我们在列表中的下一个对象上
其他的
{
entriesList.Add(当前项);
currentItem=新列表();
}
}
currentItem.Add(条目);
}
//添加最后一个当前项,因为我们无法在foreach循环中添加
entriesList.Add(当前项);
返回条目列表;
}
公共T GetFromQueryString(列出queryObject),其中T:new()
{
var obj=新的T();
var properties=typeof(T).GetProperties();
foreach(queryObject中的字符串条目)
{
字符串[]entryData=entry.Split(“”);
foreach(属性中的var属性)
{
if(entryData[0].Contains(property.Name))
{
var value=Parse(entryData[1],property.PropertyType);
如果(值==null)
继续;
SetValue(obj,value,null);
public class SampleWrapperClass : PostOBjectBase
{
    public string rawQueryString { get; set; }
    public List<ObjectToParseTo> entryList
    {
        get
        {
            List<List<string>> entriesList = GetQueryObjectsAsStringLists(rawQueryString);

            List<ObjectToParseTo> entriesFormatted = new List<ObjectToParseTo>();

            foreach (List<string> currentObject in entriesList)
            {
                ObjectToParseToentryPost = GetFromQueryString<ObjectToParseTo>(currentObject);
                entriesFormatted.Add(entryPost);
            }

            return entriesFormatted;
        }
    }
}
 JObject json;
 Request.RequestUri.TryReadQueryAsJson(out json);
 string sjson = JsonConvert.SerializeObject(json);
 StarBuildParams query = JsonConvert.DeserializeObject<StarBuildParams>(sjson);