我们在日志中开始看到这个,知道从哪里开始寻找问题?调用堆栈中没有任何内容可以帮助我们开始。
Message :An item with the same key has already been added. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at
System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean
add) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at
System.Web.Mvc.JsonValueProviderFactory.EntryLimitedDictionary.Add(String key,
Object value) at
System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary
backingStore, String prefix, Object value) at
System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary
backingStore, String prefix, Object value) at
System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) at
System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) at
System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) at
System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) at
System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) at
System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext) at System.Web.Mvc.ValueProviderFactoryCollection.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory) at
System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() at
System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() at
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at
System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at
System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) at System.Web.Mvc.ControllerBase.get_ValueProvider() at
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) at
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.
<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) at
System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) at
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object
state) at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) at
System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) at
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) at
System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) at
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) at
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) at
System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) at
System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) at
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) at
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) at
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) at
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
答案 0 :(得分:3)
当您的控制器方法收到json时,DefaultModelBinder
使用JsonValueProviderFactory
,JavaScriptSerializer
使用DictionaryValueProvider
反序列化json字符串,并将名称/值对添加到传递给的字典中{ name: someValue, NAME: anotherValue }
反过来提供绑定值。
您的错误是由于您的json包含具有重复属性名称的对象引起的,例如name: someValue
因此,一旦将NAME: anotherValue
添加到字典中,添加ValueProvideFactory
会引发异常,因为重复(不区分大小写)键。这是有道理的,因为模型不能包含2个具有相同名称的属性。
虽然最好的解决方案是跟踪并纠正'无效' json的来源,但您可以编写自己的yourProject.ValueProviderFactories
来仅绑定第一个值并忽略后续值用同一把钥匙。要保存重新发明轮子,请使用以下步骤:
using System.Web.Mvc;
)和
添加InvalidJsonValueProviderFactory
声明private class EntryLimitedDictionary
)修改public void Add(string key, object value)
{
if (++_itemCount > _maximumDepth)
{
// throw new InvalidOperationException(MvcResources.JsonValueProviderFactory_RequestTooLarge);
}
// Add the following if block
if (_innerDictionary.ContainsKey(key))
{
return;
}
_innerDictionary.Add(key, value);
}
global.asax.cs
将以下内容添加到ValueProviderFactories.Factories.Insert(0, new yourProject.ValueProviderFactories.InvalidJsonValueProviderFactory());
文件
JsonValueProviderFactory
请注意,首先需要添加它,因为private int _index = 0;
....
if (_innerDictionary.ContainsKey(key))
{
string invalidKey = string.Format("duplicates[{0}]", _index++);
string invalidValue = string.Format("{0}|{1}", key, value);
_innerDictionary.Add(invalidKey, invalidValue);
return;
}
已添加到工厂集合中。
这会阻止您的异常,但当然意味着重复属性将被丢弃。如果您重要的是重复,那么您可以考虑进行更多修改以创建具有包含索引器的不同唯一键的新词典条目,例如
index
其中string[] duplicates
从零开始并且每次都递增。然后,您可以在方法{"propertyKeys":[{"name":"name","dataType":"String","cardinality":"SINGLE"},{"name":"languages","dataType":"String","cardinality":"SET"},{"name":"picture","dataType":"String","cardinality":"SINGLE"},{"name":"preferred_language","dataType":"String","cardinality":"SINGLE"},{"name":"bytes","dataType":"Integer","cardinality":"SINGLE"},{"name":"github_id","dataType":"String","cardinality":"SINGLE"},{"name":"twitter_id","dataType":"String","cardinality":"SINGLE"},{"name":"language_percentage","dataType":"Float","cardinality":"SINGLE"}],"vertexLabels":[{"name":"person"},{"name":"language"}],"edgeLabels":[{"name":"codes_in","multiplicity":"MULTI"},{"name":"used_by","multiplicity":"MULTI"}],"vertexIndexes":[{"name":"vByName","propertyKeys":["name"],"composite":true,"unique":false},{"name":"vByPreferredLang","propertyKeys":["preferred_language"],"composite":true,"unique":false},{"name":"vByLanguages","propertyKeys":["languages"],"composite":false,"unique":false}],"edgeIndexes":[{"name":"eByName","propertyKeys":["name"],"composite":true,"unique":false},{"name":"eByLanguagePercentage","propertyKeys":["language_percentage"],"composite":true,"unique":false}]}
中添加一个附加参数,该参数将填充重复值。至少它有助于调试问题的根源。
答案 1 :(得分:0)
我想问题是当你在Dictionary中插入新的相同键值时,那个时候你不会检查Key是否存在,所以当你插入已经存在的键时会发生这个问题。简单的解决方案是在插入之前只检查密钥是否存在。
// Create Dictionary with two key value pairs.
var dictionary = new Dictionary<string, int>()
{
{"mac", 1000},
{"windows", 500}
};
// Use ContainsKey method. To check Linux is exist or not
if (dictionary.ContainsKey("linux") == false)
{
dictionary.Add("linux",300);
} else
{
Console.WriteLine("linux is already Exist");
}
在上面的例子中,mac,window和linux是目录的关键。目录有一个规则它永远不会再添加存在键。所以你必须在添加之前检查。