asp.net-mvc-3 – 构造函数注入用作Action方法参数的View Model
创建视图模型时,您可以将选项(例如,在下拉列表中使用)填充到视图模型的setter属性中.
问题是,当该视图模型稍后作为参数(通过框架!)传递到动作方法时,这些属性值不会自动变为 重新填充,因此如果由于验证错误需要重新显示表单,则需要再次重新填充这些选项. 我在这个问题中特别要求的一个潜在解决方案是如何使MVC框架使用构造函数注入实例化视图模型,这将为视图模型构造函数提供某种数据访问对象的实现(例如,存储库) )当视图请求选项时,它们可用于检索选项(例如,在辅助方法“DropDownListFor”中)? 我认为该解决方案可能与IModelBinderProvider或IModelBinder的实现有关,但是在网络上的示例代码片段中对这些事情进行了实验后,我仍在寻找一个完全可行的示例,可下载的可执行代码没有任何遗漏将所有事物放在一起的方法. 如果您正在寻找有关如何填充选择列表的替代讨论,例如使用“Dependecy Lookup”而不是“Dependecy Injection”,您可能需要查看以下讨论: 几天前,我在该帖子中写了关于“Dependecy Injection”的以下后续问题,我正在寻找这个帖子: 但是,我没有希望有人会找到那个标题较少的旧帖子,而是用一个更具体的主题来创建这个新问题,我正在寻找什么. 解决方法
我假设你想让你的ViewModel通过他们的构造函数自动注入一些东西 – 例如某种配置对象,View将用它来确定要显示的内容.我还假设当MVC尝试从Controller Action的参数自动创建和绑定模型实例时,这种方法导致“为此对象定义的无参数构造函数”错误.然后我们假设我们将使用DI框架在运行时自动将SiteConfig对象注入到我们的控制器中.
这意味着我们必须解决的唯一问题是如何在Controller自动绑定时将Controller中的注入对象引入其Actions的ViewModel. 因此,让我们为其他人继承基础模型. BaseViewModel public class BaseViewModel { public ISiteConfig SiteConfig { get; set; } public BaseViewModel(ISiteConfig siteConfig) { this.SiteConfig = siteConfig; } } 现在让我们创建一个继承它的模型. IndexViewModel public class IndexViewModel : BaseViewModel { public string SomeIndexProperty { get; set; } public IndexViewModel (ISiteConfig siteConfig) : base(siteConfig) {} } 现在让我们定义一个控制器将继承的基本控制器. BaseController public abstract class BaseController : Controller { protected BaseController(ISiteConfig siteConfig) { _siteConfig = siteConfig; } private readonly ISiteConfig _siteConfig; public ISiteConfig SiteConfig { get { return _siteConfig; } } } 现在我们定义实际的控制器. HomeController的 public HomeController: BaseController { public HomeController(ISiteConfig siteConfig): base(siteConfig) {} } 假设我们将Ninject用于DI,Ninject将被配置为自动创建Controller并在运行时将具体的ISiteConfig对象传递给其构造函数. 现在我们将Action添加到Controller. 指数行动 public ActionResult Index(IndexViewModel model) { return View(model); } 因此,如果您尝试调用Index Action,MVC将在没有做任何其他事情的情况下爆炸,并且会出现“无参数构造函数”错误,因为MVC无法找到不带参数的ViewModel构造函数. 所以,答案.我们需要覆盖默认的ModelBinder. BaseViewModelBinder public class BaseViewModelBinder : DefaultModelBinder { protected override object CreateModel(ControllerContext controllerContext,ModelBindingContext bindingContext,Type modelType) { if (modelType == typeof(BaseViewModel) || modelType.IsSubclassOf(typeof(BaseViewModel))) { var baseControl = controllerContext.Controller as BaseController; if (baseControl == null) { throw new Exception("The Controller must derive from BaseController"); } var instance = Activator.CreateInstance(modelType,baseControl.SiteConfig); bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance,modelType); return instance; } else { return base.CreateModel(controllerContext,bindingContext,modelType); } } } 我们需要将它设置为global.asax.cs中的默认模型绑定器: protected void Application_Start() { ... ModelBinders.Binders.DefaultBinder = new BaseViewModelBinder(); } 就这样.如您所见,当您立即查看索引操作时,MVC将使用我们的自定义模型绑定器.它将意识到IndexViewModel派生自BaseViewModel,因此将尝试使用它可以在Action的Controller中找到的ISiteConfig来启动IndexViewModel实例(因为Controller派生自BaseController). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 如何在codenameone中使用ASP.Net wsdl web服务
- asp.net-mvc – 在MVC3或MVC4中检查项目构建
- asp.net – 运行示例应用程序时出错,Uncaught Error:Signa
- asp.net-core – xunit无法使用ASP.NET Core RC2进行编译
- asp.net-mvc-3 – MVC站点地??图提供程序 – 在痕迹路径中维
- asp如何判断进入网站的客户是手机还是pc
- asp.net – 使用WebHandler的HTTPHandler和IsReusable
- asp.net – 在实体框架中使用PersianCalendar作为表列的正确
- asp.net-mvc – 任何潜在的安全风险设置,打开relaxedUrlToF
- ASP.NET LinkBut??ton / ImageButton和JQuery验证?
- asp.net-mvc – ASP.NET MVC内联Razor变量
- asp.net – LINQ to SQL – 如何选择特定的列和返
- asp.net – 如何从网络外部的外部站点允许内部MV
- asp.net-mvc – 没有html值的Razor属性
- asp.net-mvc – Asp.Net MVC主题,如何?
- asp.net-mvc-4 – 使用RabbitMQ从ASP.net MVC 4消
- "<a href='../目录" +变量+ 
- asp.net – Microsoft.Web.Infrastructure.dll痛
- asp.net – Handles子句需要在包含类型或其基类型
- 垃圾收集 – ASP.NET核心Web应用程序(.NET Frame