我有这个(简化的)课程:
public class StarBuildParams
{
public int BaseNo { get; set; }
public int Width { get; set; }
}
我必须将它的实例转换为这样的查询字符串:
"BaseNo=5&Width=100"
此外,我必须将这样的查询字符串转换回该类的对象。
我知道这几乎就是一个模型绑定器所做的事情,但是在我的情况下我没有控制器上下文(一些在线程中运行的深埋类)。
那么,是否有一种简单的方法可以在没有控制器上下文的情况下转换查询字符串中的对象并返回?
使用模型绑定会很棒,但我不知道如何。
答案 0 :(得分:27)
您可以使用反射,如下所示:
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;
}
你需要实现Parse方法,只需使用int.Parse,decimal.Parse,DateTime.Parse等。
答案 1 :(得分:14)
将此Parse方法与ivowiblo的解决方案(已接受的答案)一起使用:
public object Parse(string valueToConvert, Type dataType)
{
TypeConverter obj = TypeDescriptor.GetConverter(dataType);
object value = obj.ConvertFromString(null, CultureInfo.InvariantCulture, valueToConvert);
return value;
}
答案 2 :(得分:9)
使用Newtonsoft Json序列化程序和linq的解决方案:
[]
[10]
[10, 20]
Segmentation fault: 11
答案 3 :(得分:4)
您可以通过从查询字符串中检索相关值来在其构造函数中设置此对象的属性
public StarBuildParams()
{
this.BaseNo = Int32.Parse(Request.QueryString["BaseNo"].ToString());
this.Width = Int32.Parse(Request.QueryString["Width"].ToString());
}
您可以通过覆盖ToString
方法确保将对象转换为正确的查询字符串格式。
public override string ToString()
{
return String.Format("BaseNo={0}&Width={1}", this.BaseNo, this.Width);
}
你仍然需要在适当的地方构建和调用ToString
,但这应该会有所帮助。
答案 4 :(得分:4)
只要没有任何属性匹配任何其他路由参数(如controller,action,id等),这应该可以工作。
new RouteValueDictionary(Model)
http://msdn.microsoft.com/en-us/library/cc680272.aspx
初始化RouteValueDictionary类的新实例并添加 基于指定对象的属性的值。
要从查询字符串中解析回来,您可以将模型类用作操作参数,并让ModelBinder完成它的工作。
答案 5 :(得分:1)
您可以使用.NET的HttpUtility.ParseQueryString()
方法:
HttpUtility.ParseQueryString("a=b&c=d")
生成NameValueCollection
:
[0] Key = "a", Value = "b"
[1] Key = "c", Value = "d"
答案 6 :(得分:0)
以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;
}
}
然后,您可以从包装类中继承此类,以进行POST请求并解析为所需的任何对象。在这种情况下,代码将解析作为查询字符串传递给包装类对象列表的对象列表。
例如:
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;
}
}
}
答案 7 :(得分:0)
序列化查询字符串并反序列化到您的类对象
<layout class="QVBoxLayout" name="vlayout">