我是MVC的新手,虽然我一直在尝试遵循最佳做法,但我相信我可能对这两个方面的某些基本知识都不了解
-一个。适当使用模型和视图模型
-b。将模型传递到控制器中以进行验证。
我程序的一般目的是从存储过程列表中选择一个存储过程,创建一个表单,用户可以在其中填写所有适当的输入变量,然后执行该存储过程。该工具适用于非技术人员,因此我最终将不得不进行大量的输入验证。
因此,我有四个模型:一个脚本模型,一个参数模型,一个参数枚举模型和一个查询模型,以及两个视图模型:一个paramviewmodel生成要填写的表单,一个scriptviewmodel创建一个用可能的脚本填充的列表框选择。我正在使用预写的数据库系统在控制器的init方法中填充我的视图模型(我不确定这样做的正确方法吗?)。
视图模型如下:
Imports System
Imports System.Collections.Generic
Public Class ScriptViewModel
Public Property SelectedItemId As Integer
Public Property Scripts As DataTable
Public Property ScriptList As List(Of ScriptModel)
Sub InitScriptData()
' Fills the data from an outside database.
' And fills out the properties above. Does nothing else
End Sub
End Class
另外一个
Imports System
Imports System.Collections.Generic
Public Class ParamViewModel
Public Property Params As DataTable
Public Property ParamEnums As DataTable
Public Property ParameterList As List(Of ParameterModel)
Public Property ParamEnumList As List(Of ParamEnumModel)
Public Property ParamEnumDictionary As Dictionary(Of Integer, List(Of ParamEnumModel))
Sub InitParamData(ByVal Script_Index As String)
' Uses an outside database
' Fills out all the above variables
End Sub
End Class
它们的关联视图如下所示:
脚本:
@ModelType Scripter.ScriptViewModel
@Html.ValidationSummary("Please correct the errors and try again.")
@Using (Html.BeginForm("ParamChoice", "Parameter", FormMethod.Post))
@<div>
@Html.ListBox("ScriptListBox", New SelectList(Model.ScriptList, "Script_Index", "CustomerScriptName"), New With {.class = "LargeListBox", .title = "LargeListBox"})
</div>
@<input type="submit" value="Execute Script" />
End Using
ParamChoice:
@ModelType Scripter.ParamViewModel
@Code
ViewData("Title") = "ParamChoice"
End Code
<h2>ParamChoice</h2>
<!-- Helper Method defined in App_Code that creates a form with a dynamic number of fields of appropriate input types -->
@HelperMethods.CreateVariableInputParameterFields(Model.ParameterList, Model.ParamEnumDictionary)
助手说(这是我的主要困惑所在)(请注意,继承帮助页面是指一个类,该类允许我在app_code的@helper中使用htmlhelper)
@inherits Scripter.HelperPage
@Imports System.Web.Mvc
@Imports System.Web.Mvc.Html
@helper CreateVariableInputParameterFields(ByVal ParamList As List(Of Scripter.ParameterModel), ByVal EnumDictionary As Dictionary(Of Integer, List(Of Scripter.ParamEnumModel)))
Dim item As Scripter.ParameterModel
@Html.ValidationSummary("Please correct the errors and try again.")
Using (Html.BeginForm("QueryServer", "Query", FormMethod.Post))
Dim iterator As Integer = 0
Dim ParamValue(ParamList.Count) As String
Dim ParamName(ParamList.Count) As String
Dim ParamType(ParamList.Count) As String
For Each item In ParamList
If (String.Compare(item.ParamType, "Int") = 0 Or String.Compare(item.ParamType, "String") = 0) Then
@<br />
@Html.Label(item.ParamName)
@Html.TextBox("ParamValue", Nothing, New With {.class = "text-box", .id = CStr(iterator)})
@Html.Hidden("ParamName", item.ParamName, New With {.id = CStr(iterator)})
@Html.Hidden("ParamType", item.ParamType, New With {.id = CStr(iterator)})
iterator += 1
ElseIf (String.Compare(item.ParamType.ToString, "Enum") = 0) Then
Dim tlist = EnumDictionary.Item(item.Param_Index)
@<br />
@Html.Label("label", item.ParamName, New With {.class = "display-label"})
@Html.DropDownList("ParamValue", New SelectList(tlist, "EnumValue", "EnumValue"), New With {.id = CStr(iterator)})
@Html.Hidden("ParamName", item.ParamName, New With {.id = CStr(iterator)})
@Html.Hidden("ParamType", item.ParamType, New With {.id = CStr(iterator)})
iterator += 1
Else
@<br />
@Html.Label("label", item.ParamName, New With {.class = "display-label"})
@Html.CheckBox("ParamValue", Nothing, New With {.id = CStr(iterator)})
@Html.Hidden("ParamName", item.ParamName, New With {.id = CStr(iterator)})
@Html.Hidden("ParamType", item.ParamType, New With {.id = CStr(iterator)})
iterator += 1
End If
Next
@Html.Hidden("Script_Index", ParamList.Item(0).Script_Index)
@<div>
<input type="submit" value="Query Server"/>
</div>
Html.EndForm()
End Using
End helper
脚本控制器作为我一直在做的一个例子:
Namespace Scripter
Public Class ScriptController
Inherits System.Web.Mvc.Controller
Function Index() As ActionResult
Dim Test As New ScriptViewModel
Test.InitScriptData()
Return View(Test)
End Function
End Class
End Namespace
抱歉,上面的所有内容都很丑陋,我正在尝试确定其功能。另外,我认为这在视图中可能是太多代码,即使其中大多数是显示代码。
无论如何,我有两个主要问题。第一,在控制器中创建模型,调用其init方法,然后将其传递给视图在mvc上下文中是否有意义(如果没有,我将如何进行?)。第二,如果我想对在htmlhelper中输出的表单执行验证,但是我想使用查询模型验证(而不是我的paramviewmodel),该怎么做?我见过的大多数示例都涉及一个控制器,该控制器接收适当的模型变量,并且绑定是在控制器本身之外执行的。然后,他们只是检查modelstate。有什么办法可以在这里做类似的事情吗?
请随时在此处记下我的代码。我是这个的super新手(vb.net和mvc都没有),还没有机会拿起一本书。我一直在网上搜集资料,但是我确定我做错了很多事情。
编辑:有什么办法可以使语法突出显示的内容更糟?
最佳答案
通常,视图模型不打算具有将从数据库中获取数据的Init方法。在大多数情况下,视图模型是标准的POCO类,其中包含将保存特定视图需要使用的数据的属性。
另一方面,您可能具有一个或多个域模型,这些模型将负责从各种数据源中检索信息。
控制器操作将负责查询您的域模型及其各种方法,以便最终构建将被处理以显示的特定视图模型。视图模型可以表示从多个域模型和各种数据源聚合的数据。
因此,基本上,这是标准GET控制器操作的伪代码:
Function Index() As ActionResult
Dim model1 As DomainModel1 = ... fetch the domain model from somewhere
Dim model2 As DomainModel2 = ... fetch the domain model from somewhere
Dim vm As ViewModel = ... map all the domain models to a single view model specifically designed for the view
Return View(vm)
End Function
在这里,域模型负责从您正在使用的各种数据源(数据库,文件,远程Web服务等)中获取数据。视图模型只是该数据以适合于视图的方式的投影。