GET 请求的 List<X> 参数的 MVC 自定义序列化?
MVC custom serialization of List<X> parameter for GET request?
我想将请求更改为 GET 而不是 POST,以便用户可以共享生成的 URL。
当前系统使用普通表单提交,并利用表单提交和自定义对象列表的 MVC ActionResult 之间的自动序列化。
例如
<form action="/MyPage">
<input type="hidden" id="MyThings_0__Value" name="MyThings[0].Value">
<input type="hidden" id="MyThings_0__Flag" name="MyThings[0].Flag">
<input type="hidden" id="MyThings_1__Value" name="MyThings[1].Value">
<input type="hidden" id="MyThings_1__Flag" name="MyThings[1].Flag">
</form>
但是这样做会导致生成的GET字符串过长和复杂。这很糟糕,因为 MyThings
列表最多可以包含 10 个项目。
http://myurl.com/MyPage?MyThings%5B0%5D.Value=ThisIsValue1&MyThings%5B0%5D.Flag=1&MyThings%5B1%5D.Value=ThisIsValue2&MyThings%5B1%5D.Flag=2
我希望该字符串看起来更加用户友好。类似于:
http://myurl.com/MyPage?MyThings=ThisIsValue1-1,ThisIsValue2-2
这可以通过自定义序列化来完成吗?如果是这样,我将如何实施它?
我的模型和 ActionResult:
namespace MyNamespace {
public class MyThing {
public string Value { get; set; }
public int Flag { get; set; }
}
public class Filter {
public string CustomAttribute1 { get; set; }
public string CustomAttribute2 { get; set; }
public string CustomAttribute3 { get; set; }
public List<MyThing> MyThings { get; set; } = new List<MyThing>();
}
public ActionResult MyPage(Filter filter) {
MyModel model = StaticMethod.GetMyModel(filter);
return View(model);
}
}
最后我决定不使用自定义 URL 序列化,而是使用辅助方法在 C# 模型中向后和向前转换为 string/class。
public class Filter {
public string MyThing { get; set; }
public List<MyThingClass> MyThings {
get {
if (this._myThings == null) { // Default to Query string
this._myThings = ToQueryList(this.MyThing);
}
return this._myThings;
}
set {
this.MyThing = ToQueryString(value); // Automatically assign QueryString to serialized QueryItems on set
this._myThings = value;
}
}
private List<MyThingClass> _myThings { get; set; }
public static List<MyThingClass> ToQueryList(string queryString) {
return queryString.Split(',').Select(x => MyThingClass.FromString(x)).ToList();
}
public static string ToQueryString(List<MyThingClass> myThings) {
return string.Join(",", myThings.Select(x => x.ToString()));
}
}
public class MyThingClass {
public string Value { get; set; }
public int Flag { get; set; }
/// <summary>Converts a QueryItem object to a serialized object ready for the QueryString.</summary>
public override string ToString() {
return string.Concat(this.Value, "-", this.Flag);
}
public static MyThingClass FromString(string value) {
var v = value.Split('-');
return new MyThingClass() {
Value = v[0],
Flag = Convert.ToInt32(v[1])
};
}
}
我想将请求更改为 GET 而不是 POST,以便用户可以共享生成的 URL。
当前系统使用普通表单提交,并利用表单提交和自定义对象列表的 MVC ActionResult 之间的自动序列化。
例如
<form action="/MyPage">
<input type="hidden" id="MyThings_0__Value" name="MyThings[0].Value">
<input type="hidden" id="MyThings_0__Flag" name="MyThings[0].Flag">
<input type="hidden" id="MyThings_1__Value" name="MyThings[1].Value">
<input type="hidden" id="MyThings_1__Flag" name="MyThings[1].Flag">
</form>
但是这样做会导致生成的GET字符串过长和复杂。这很糟糕,因为 MyThings
列表最多可以包含 10 个项目。
http://myurl.com/MyPage?MyThings%5B0%5D.Value=ThisIsValue1&MyThings%5B0%5D.Flag=1&MyThings%5B1%5D.Value=ThisIsValue2&MyThings%5B1%5D.Flag=2
我希望该字符串看起来更加用户友好。类似于:
http://myurl.com/MyPage?MyThings=ThisIsValue1-1,ThisIsValue2-2
这可以通过自定义序列化来完成吗?如果是这样,我将如何实施它?
我的模型和 ActionResult:
namespace MyNamespace {
public class MyThing {
public string Value { get; set; }
public int Flag { get; set; }
}
public class Filter {
public string CustomAttribute1 { get; set; }
public string CustomAttribute2 { get; set; }
public string CustomAttribute3 { get; set; }
public List<MyThing> MyThings { get; set; } = new List<MyThing>();
}
public ActionResult MyPage(Filter filter) {
MyModel model = StaticMethod.GetMyModel(filter);
return View(model);
}
}
最后我决定不使用自定义 URL 序列化,而是使用辅助方法在 C# 模型中向后和向前转换为 string/class。
public class Filter {
public string MyThing { get; set; }
public List<MyThingClass> MyThings {
get {
if (this._myThings == null) { // Default to Query string
this._myThings = ToQueryList(this.MyThing);
}
return this._myThings;
}
set {
this.MyThing = ToQueryString(value); // Automatically assign QueryString to serialized QueryItems on set
this._myThings = value;
}
}
private List<MyThingClass> _myThings { get; set; }
public static List<MyThingClass> ToQueryList(string queryString) {
return queryString.Split(',').Select(x => MyThingClass.FromString(x)).ToList();
}
public static string ToQueryString(List<MyThingClass> myThings) {
return string.Join(",", myThings.Select(x => x.ToString()));
}
}
public class MyThingClass {
public string Value { get; set; }
public int Flag { get; set; }
/// <summary>Converts a QueryItem object to a serialized object ready for the QueryString.</summary>
public override string ToString() {
return string.Concat(this.Value, "-", this.Flag);
}
public static MyThingClass FromString(string value) {
var v = value.Split('-');
return new MyThingClass() {
Value = v[0],
Flag = Convert.ToInt32(v[1])
};
}
}