我正在尝试在TypeScript中构建搜索过滤器值及其显示名称的字典,以便在AJAX请求中将其作为可序列化/可反序列化的TypeScript对象以及MVC模型中的JSON字符串发送到服务器。我将反序列化的数据映射到以下C#结构:
public struct AvailableSearchFilters
{
public IDictionary<string, string> Users { get; set; }
public IDictionary<string, string> Contracts { get; set; }
}
public struct SelectedSearchFilters
{
public IEnumerable<string> UserIds { get; set; }
public IEnumerable<string> ContractIds { get; set; }
}
public struct SearchFilters
{
public AvailableSearchFilters AvailableSearchFilters { get; set; }
public SelectedSearchFilters SelectedSearchFilters { get; set; }
}
我在这个JQuery AJAX调用中通过在TypeScript中复制这些类来发送这些数据(每个类都有一个构造函数用于分配所有属性)。
我通过分配一个表示模型上字符串属性的隐藏表单字段将数据发送到我的MVC控制器;为此我通过JSON.stringify
传递TypeScript模型,然后在C#控制器调用的另一端传递:
JsonConvert.DeserializeObject<SearchFilters>(
myMvcModel.StringifiedSearchFilters,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore
});
哪个应该得到我的模型但是失败并出现以下错误:
Newtonsoft.Json.JsonSerializationException:无法反序列化 当前的JSON数组(例如[1,2,3])成类型 &#39; System.Collections.Generic.IDictionary`2 [System.String,System.String]&#39; 因为类型需要一个JSON对象(例如{&#34; name&#34;:&#34; value&#34;})来 正确反序列化。要修复此错误,请将JSON更改为a JSON对象(例如{&#34; name&#34;:&#34; value&#34;})或将反序列化类型更改为 实现集合接口的数组或类型(例如, ICollection,IList)就像可以从JSON反序列化的List一样 阵列。 JsonArrayAttribute也可以添加到类型中以强制它 从JSON数组反序列化。
我已经设法构建了一个TypeScript对象,它可以成功地反序列化为第一个方法的C#结构(通过使用我创建的自定义KeyValuePair.ts
来匹配.NET Dictionary中的那个)但是当它来到第二种方法,它以一种方式序列化(使用JSON.stringify
),KeyValuePairs每个都标有&#34; Key&#34;或&#34;价值&#34;这与使用JsonConvert.SerializeObject(new SearchFilters(...))
(将反序列化回SearchFilters
对象)时的输出不同,奇怪地将每个键作为平面数组中每个值的标签。
这是我用来在客户端获取SearchFilter对象的方法。
private getSearchFilters(): LogAnalysisFilters
{
return new SearchFilters(
new AvailableSearchFilters
(
[
new KeyValuePair("2", "Smith Corp Virtual Reality Agreement"),
new KeyValuePair("8", "Flexible Spoons Revision")
],
[
new KeyValuePair("12", "John Smith"),
new KeyValuePair("24", "Thomas Anderson")
]
),
new SelectedFilters
(
["2"],
["12", "14"]
));
}
然后我将结果传递给AJAX调用:
$.ajax(
{
dataType: 'json',
url: "/Something/MyController/UpdateOnScreenData",
method: 'Post',
data: { SearchFilters: this.getSearchFilters() },
cache: false,
success: (result) => { successCallback(result); },
error: (error) => { errorCallback(error) }
});
哪个有效并且在C#中为我提供了正确解析的模型。
我将TypeScriptObject传递给它,以分配给MVC模型的字符串属性相应的隐藏表单字段:
$("#stringifiedSearchFilters").val(JSON.stringify(this.getSearchFilters()));
但是当它通过MVC方法(通过HttpPost)对其进行反序列化时,它处于一种不可序列化的格式,与内存中的样本不同。
[HttpPost]
public ActionResult DoSomethingWithSearchFiltersJson(MyMvcModel myMvcModel)
{
var inMemorySearchFiltersJson = JsonConvert.SerializeObject(
new SearchFilters(
new AvailableSearchFilters
{
Contracts = new Dictionary<string, string>
{
{ "2", "Smith Corp Virtual Reality Agreement" },
{ "8", "Flexible Spoons Revision" }
},
Users = new Dictionary<string, string>
{
{ "12", "John Smith" },
{ "24", "Thomas Anderson" }
}
},
new SelectedSearchFilters
{
SelectedContractIds = new[] { 2 },
SelectedCatOperatorUserIds = new[] { 12, 24 }
}));
var clientSearchFiltersJson = myMvcModel.StringifiedSearchFilters;
var clientSearchFilters = JsonConvert.DeserializeObject<SerializedLogAnalysisFilters>(
clientSearchFiltersJson,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore
});
}
inMemorySearchFiltersJson:
"{\"AvailableSearchFilters\":{\"Contracts\":{\"2\":\"Smith Corp Virtual Reality Agreement\",\"8\":\"Flexible Spoons Revision\"},\"Users\":{\"12\":\"John Smith\",\"24\":\"Thomas Anderson\"}},\"SelectedSearchFilters\":{\"ContractIds\":[2],\"UserIds\":[12,24]}}"
clientSearchFiltersJson:
"{\"AvailableSearchFilters\":{\"Contracts\":[{\"Key\":\"2\",\"Value\":\"Smith Corp Virtual Reality Agreement\"},{\"Key\":\"8\",\"Value\":\"Flexible Spoons Revision\"}],\"Users\":[{\"Key\":\"12\",\"Value\":\"John Smith\"},{\"Key\":\"24\",\"Value\":\"Thomas Anderson\"}]},\"SelectedSearchFilters\":{\"ContractIds\":[\"2\"],\"UserIds\":[\"12\",\"24\"]}}"
为什么JSON.stringify输出与两个等效模型(TypeScript和C#)的JsonConvert.Serialize输出不同?如果我需要更改TypeScript模型,那么我不希望它破坏当前有效的MVC AJAX请求解析。
或者(实际上最好)有一种方法可以将非像这样的复杂TypeScript对象发送到非AJAX HttpPost中的服务器,让MVC像AJAX调用一样处理序列化/反序列化吗?最好将字符串化的TypeScript对象分配给隐藏的表单字段,并尝试在服务器端尝试解析它(就像目前的情况一样)。