U4-6721 Error when submitting Macros, Collection was modified; enumeration operation may not execute. (after project has been updated to MVC5)
#U4-6721 In Progress
This commit is contained in:
@@ -143,7 +143,7 @@ namespace Umbraco.Web.Macros
|
|||||||
//bubble up the model state from the main view context to our custom controller.
|
//bubble up the model state from the main view context to our custom controller.
|
||||||
//when merging we'll create a new dictionary, otherwise you might run into an enumeration error
|
//when merging we'll create a new dictionary, otherwise you might run into an enumeration error
|
||||||
// caused from ModelStateDictionary
|
// caused from ModelStateDictionary
|
||||||
controller.ModelState.MergeSafe(new ModelStateDictionary(viewContext.ViewData.ModelState));
|
controller.ModelState.Merge(new ModelStateDictionary(viewContext.ViewData.ModelState));
|
||||||
controller.ControllerContext = new ControllerContext(request, controller);
|
controller.ControllerContext = new ControllerContext(request, controller);
|
||||||
//call the action to render
|
//call the action to render
|
||||||
var result = controller.Index();
|
var result = controller.Index();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -7,51 +8,24 @@ namespace Umbraco.Web
|
|||||||
{
|
{
|
||||||
internal static class ModelStateExtensions
|
internal static class ModelStateExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Safely merges ModelState
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="state"></param>
|
|
||||||
/// <param name="dictionary"></param>
|
|
||||||
/// <remarks>The MVC5 System.Web.Mvc.ModelStateDictionary.Merge method is not safe</remarks>
|
|
||||||
public static void MergeSafe(this ModelStateDictionary state, ModelStateDictionary dictionary)
|
|
||||||
{
|
|
||||||
if (dictionary == null)
|
|
||||||
return;
|
|
||||||
// Need to stuff this into a temporary new dictionary that we're allowed to alter,
|
|
||||||
// if we alter "state" in this enumeration, it fails with
|
|
||||||
// "Collection was modified; enumeration operation may not execute"
|
|
||||||
var tempDictionary = new ModelStateDictionary(state);
|
|
||||||
foreach (var entryKey in dictionary.Keys)
|
|
||||||
{
|
|
||||||
tempDictionary[entryKey] = dictionary[entryKey];
|
|
||||||
}
|
|
||||||
// Update state with updated dictionary
|
|
||||||
state = tempDictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Merges ModelState that has names matching the prefix
|
/// Merges ModelState that has names matching the prefix
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state"></param>
|
/// <param name="state"></param>
|
||||||
/// <param name="dictionary"></param>
|
/// <param name="dictionary"></param>
|
||||||
/// <param name="prefix"></param>
|
/// <param name="prefix"></param>
|
||||||
public static void Merge(this ModelStateDictionary state, ModelStateDictionary dictionary, string prefix)
|
public static void Merge(this ModelStateDictionary state, ModelStateDictionary dictionary, string prefix)
|
||||||
{
|
{
|
||||||
if (dictionary == null)
|
if (dictionary == null)
|
||||||
return;
|
return;
|
||||||
// Need to stuff this into a temporary new dictionary that we're allowed to alter,
|
foreach (var keyValuePair in dictionary
|
||||||
// if we alter "state" in this enumeration, it fails with
|
|
||||||
// "Collection was modified; enumeration operation may not execute"
|
|
||||||
var tempDictionary = new ModelStateDictionary(state);
|
|
||||||
foreach (var keyValuePair in dictionary
|
|
||||||
//It can either equal the prefix exactly (model level errors) or start with the prefix. (property level errors)
|
//It can either equal the prefix exactly (model level errors) or start with the prefix. (property level errors)
|
||||||
.Where(keyValuePair => keyValuePair.Key == prefix || keyValuePair.Key.StartsWith(prefix + ".")))
|
.Where(keyValuePair => keyValuePair.Key == prefix || keyValuePair.Key.StartsWith(prefix + ".")))
|
||||||
{
|
{
|
||||||
tempDictionary[keyValuePair.Key] = keyValuePair.Value;
|
state[keyValuePair.Key] = keyValuePair.Value;
|
||||||
}
|
}
|
||||||
// Update state with updated dictionary
|
}
|
||||||
state = tempDictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if there are any model errors on any fields containing the prefix
|
/// Checks if there are any model errors on any fields containing the prefix
|
||||||
|
|||||||
@@ -138,17 +138,18 @@ namespace Umbraco.Web.Mvc
|
|||||||
/// <param name="controller"></param>
|
/// <param name="controller"></param>
|
||||||
internal static void EnsureViewObjectDataOnResult(this ControllerBase controller, ViewResultBase result)
|
internal static void EnsureViewObjectDataOnResult(this ControllerBase controller, ViewResultBase result)
|
||||||
{
|
{
|
||||||
//when merging we'll create a new dictionary, otherwise you might run into an enumeration error
|
|
||||||
// caused from ModelStateDictionary
|
|
||||||
result.ViewData.ModelState.MergeSafe(new ModelStateDictionary(controller.ViewData.ModelState));
|
|
||||||
|
|
||||||
// Temporarily copy the dictionary to avoid enumerator-modification errors
|
|
||||||
var newViewDataDict = new ViewDataDictionary(controller.ViewData);
|
|
||||||
foreach (var d in newViewDataDict)
|
|
||||||
result.ViewData[d.Key] = d.Value;
|
|
||||||
|
|
||||||
result.TempData = controller.TempData;
|
result.TempData = controller.TempData;
|
||||||
|
|
||||||
|
var newViewDataDict = new ViewDataDictionary(controller.ViewData);
|
||||||
|
var viewDataDictionary = result.ViewData;
|
||||||
|
foreach (var d in newViewDataDict)
|
||||||
|
viewDataDictionary[d.Key] = d.Value;
|
||||||
|
|
||||||
|
result.ViewData = viewDataDictionary;
|
||||||
|
|
||||||
|
foreach (var keyValuePair in controller.ViewData.ModelState.Keys)
|
||||||
|
result.ViewData[keyValuePair] = keyValuePair;
|
||||||
|
|
||||||
if (result.View != null) return;
|
if (result.View != null) return;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(result.ViewName))
|
if (string.IsNullOrEmpty(result.ViewName))
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Umbraco.Web.Mvc
|
|||||||
{
|
{
|
||||||
if (filterContext.Controller.ControllerContext.IsChildAction)
|
if (filterContext.Controller.ControllerContext.IsChildAction)
|
||||||
{
|
{
|
||||||
filterContext.Controller.ViewData.ModelState.MergeSafe(
|
filterContext.Controller.ViewData.ModelState.Merge(
|
||||||
filterContext.Controller.ControllerContext.ParentActionViewContext.ViewData.ModelState);
|
filterContext.Controller.ControllerContext.ParentActionViewContext.ViewData.ModelState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ namespace Umbraco.Web.Mvc
|
|||||||
tempDataDictionary.Save(context, new SessionStateTempDataProvider());
|
tempDataDictionary.Save(context, new SessionStateTempDataProvider());
|
||||||
var viewCtx = new ViewContext(context, new DummyView(), new ViewDataDictionary(), tempDataDictionary, new StringWriter());
|
var viewCtx = new ViewContext(context, new DummyView(), new ViewDataDictionary(), tempDataDictionary, new StringWriter());
|
||||||
|
|
||||||
viewCtx.ViewData.ModelState.MergeSafe(context.Controller.ViewData.ModelState);
|
viewCtx.ViewData.ModelState.Merge(new ModelStateDictionary(context.Controller.ViewData.ModelState));
|
||||||
|
|
||||||
foreach (var d in context.Controller.ViewData)
|
foreach (var d in context.Controller.ViewData)
|
||||||
viewCtx.ViewData[d.Key] = d.Value;
|
viewCtx.ViewData[d.Key] = d.Value;
|
||||||
@@ -124,7 +124,7 @@ namespace Umbraco.Web.Mvc
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void CopyControllerData(ControllerContext context, ControllerBase controller)
|
private static void CopyControllerData(ControllerContext context, ControllerBase controller)
|
||||||
{
|
{
|
||||||
controller.ViewData.ModelState.MergeSafe(context.Controller.ViewData.ModelState);
|
controller.ViewData.ModelState.Merge(context.Controller.ViewData.ModelState);
|
||||||
|
|
||||||
foreach (var d in context.Controller.ViewData)
|
foreach (var d in context.Controller.ViewData)
|
||||||
controller.ViewData[d.Key] = d.Value;
|
controller.ViewData[d.Key] = d.Value;
|
||||||
|
|||||||
Reference in New Issue
Block a user