基于 multi-step registration process issues in asp.net mvc (splitted viewmodels, single model) 的精彩答案,我使用 Darin Dimitrov 提供的示例来测试 ASP.net MVC3 向导。它可以独立运行,但不能在 Orchard CMS v1.3 内运行。
我收到以下错误:
Server Error in '/' Application.
Cannot create an instance of an interface.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: Cannot create an instance of an interface.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[MissingMethodException: Cannot create an instance of an interface.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241 System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +199 System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +572
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +449
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +317
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +117
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c__DisplayClassb.b__5() +37
System.Web.Mvc.Async.<>c__DisplayClass1.b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass81.<BeginSynchronous>b__7(IAsyncResult _) +12 System.Web.Mvc.Async.WrappedAsyncResult
1.End() +62 System.Web.Mvc.<>c__DisplayClasse.b__d() +50
System.Web.Mvc.SecurityUtil.b__0(Action f) +7 System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
Orchard.Mvc.Routes.HttpAsyncHandler.EndProcessRequest(IAsyncResult result) in d:\Builds\OrchardFull\src\Orchard\Mvc\Routes\ShellRoute.cs:148
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8963149 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.237
我大胆猜测是 Controller 引起了麻烦。这是代码:
[Themed]
public class WizardController : Controller
{
public ActionResult Index()
{
var wizard = new WizardViewModel();
wizard.Initialize();
return View(wizard);
}
[HttpPost]
public ActionResult Index([Deserialize] WizardViewModel wizard, IStepViewModel step)
{
wizard.Steps[wizard.CurrentStepIndex] = step;
if (ModelState.IsValid)
{
if (!string.IsNullOrEmpty(Request["next"]))
{
wizard.CurrentStepIndex++;
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
wizard.CurrentStepIndex--;
}
else
{
// TODO: we have finished: all the step partial
// view models have passed validation => map them
// back to the domain model and do some processing with
// the results
return Content("thanks for filling this form", "text/plain");
}
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
// Even if validation failed we allow the user to
// navigate to previous steps
wizard.CurrentStepIndex--;
}
return View(wizard);
}
}
但我不是 100% 确定,另一个罪魁祸首可能是 WizardViewModel:
[Serializable]
public class WizardViewModel
{
public int CurrentStepIndex { get; set; }
public IList<IStepViewModel> Steps { get; set; }
public void Initialize()
{
Steps = new IStepViewModel[]
{
new Step1ViewModel(),
new Step2ViewModel(),
new Step3ViewModel()
};
}
}
最后一部分是手动插入步骤并更改最初发布的代码(直接来自作者)。非常感谢任何帮助。
最佳答案
显然,您正在使用的模型绑定(bind)器无法从提供的接口(interface)(IStepViewModel)找到它需要实例化的模型
我非常确定默认的 ASP.NET MVC ModelBinder 无法执行此类操作,因为它需要一些自定义逻辑来选择应实例化的具体接口(interface)实现。
因此,您有两种解决方案:
- 检查您的示例,我认为它提供了一个自定义 ModelBinder,并通过实现 IModelBinderProvider 在 Orchard 中注册它
不要在 Index 操作中请求 IStepViewModel:
public ActionResult Index([Deserialize] WizardViewModel wizard, IStepViewModel step)
并将其替换为具体的类。
关于asp.net-mvc-3 - "Cannot create an instance of an Interface"(Orchard CMS 内的 MvC 3 向导),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8059433/