2013-10-29 42 views
1

編輯:我不知道我以前錯過了這一點,但這可能是Binding a dictionary containing a list in MVC4的副本。異常發佈與視圖模型與字典屬性,鍵入枚舉,類爲值

我使用ASP.NET MVC4,和我有一個鍵上的枚舉,具有類作爲它的值類型的字典屬性。我正在使用Html.TextBoxFor爲控件操作生成表單的HTML,並將其中一個作爲視圖模型。當我通過瀏覽器提交表單時,我在綁定過程中獲得InvalidCastException

這裏的視圖模型:

public class MyViewModel 
{ 
    public virtual IDictionary<MyEnumType, IList<MySubViewModel>> Subs { get; set; } 

    public class MySubViewModel 
    { 
     public virtual String Name { get; set; } 
    } 
} 

在控制器中,我有:

[HttpGet] 
public ActionResult EditPage(Int32? id) 
{ 
    MyViewModel testViewModel = new MyViewModel 
     { 
      Subs = new Dictionary<MyEnumType, IList<MyViewModel.MySubViewModel>>() { 
       { 
        MyEnumType.MySubViewModel 
        , new List<MyViewModel.MySubViewModel> { 
         new MyViewModel.MySubViewModel { 
          Name = "Foo-Bar" 
         } 
        } 
       } 
      } 
     }; 
    return View(testViewModel); 
} 

[HttpPost] 
public ActionResult EditPage(MyViewModel model) 
{ 
    return View(model); 
} 

我有我的觀點(使用Spark視圖引擎):

<tbody each="var enumValue in Html.EnumValues<MyEnumType>()"> 
    <tr each="var sub in Model.Subs[enumValue]" class="DataRow"> 
     <td> 
      ${Html.TextBoxFor(m => m.Subs[enumValue][subIndex].Name, new { @class="SubName" })} 
     </td> 
    </tr> 
</tbody> 

這被渲染爲:

<tbody> 
    <tr> 
     <td> 
      <input id="Subs_EnumValueOne__0__Name" type="text" value="Foo-Bar" name="Subs[EnumValueOne][0].Name"> 
     </td> 
    </tr> 
</tbody> 

當我提交的頁面,我得到一個InvalidCastException{"Specified cast is not valid."}

at System.Web.Mvc.DefaultModelBinder.CollectionHelpers.ReplaceDictionaryImpl[TKey,TValue](IDictionary`2 dictionary, IEnumerable`1 newContents) 

這是堆棧跟蹤。 (我有一個不同類型的模型粘結劑,但對於本字典屬性,它只是通過給base.BindModel。)

[InvalidCastException: Specified cast is not valid.] 
    System.Web.Mvc.CollectionHelpers.ReplaceDictionaryImpl(IDictionary`2 dictionary, IEnumerable`1 newContents) +131 

[TargetInvocationException: Exception has been thrown by the target of an invocation.] 
    System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0 
    System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +92 
    System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +108 
    System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +19 
    System.Web.Mvc.CollectionHelpers.ReplaceDictionary(Type keyType, Type valueType, Object dictionary, Object newContents) +178 
    System.Web.Mvc.DefaultModelBinder.UpdateDictionary(ControllerContext controllerContext, ModelBindingContext bindingContext, Type keyType, Type valueType) +1211 
    System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +921 
    System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +416 
    Namespace.For.MyBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1195 
    System.Web.Mvc.DefaultModelBinder.GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) +17 
    System.Web.Mvc.DefaultModelBinder.BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) +384 
    System.Web.Mvc.DefaultModelBinder.BindProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) +88 
    System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Object model) +53 
    System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1314 
    System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +416 
    Namespace.For.MyBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1195 
    System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +317 
    System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +117 
    System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) +446 
    System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130 
    System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +302 
    System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +30 
    System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130 
    System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +382 
    System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130 
    System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +317 
    System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +15 
    System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +71 
    System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130 
    System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +249 
    System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50 
    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16 
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

回答

0

看起來你忘了在POST重新填充您MyViewModelSubs財產行動。您必須在GETPOST請求中這樣做。

你可以將它重構爲一個方法,並調用它在這兩個動作:

private Dictionary<MyEnumType, IList<MyViewModel.MySubViewModel>> GetSubsDict() 
{ 
    return new Dictionary<MyEnumType, IList<MyViewModel.MySubViewModel>>() 
       { 
        { 
         MyEnumType.MySubViewModel, 
         new List<MyViewModel.MySubViewModel> 
         { 
          new MyViewModel.MySubViewModel 
          { 
           Name = "Foo-Bar" 
          } 
         } 
        } 
       } 
} 

的GET操作:

public ActionResult EditPage(Int32? id) 
{ 
    MyViewModel testViewModel = new MyViewModel 
            { 
             Subs = GetSubsDict(); 
            } 
    return View(testViewModel); 
} 

又在POST操作:

public ActionResult EditPage(MyViewModel model) 
{ 
    model.Subs = GetSubsDict(); 
    return View(model); 
} 
+0

執行永遠不會達到事後的行動。已發佈的數據不會綁定。如果我在POST動作的第一行放置了一個斷點,它永遠不會到達。感謝你的回答。 –