Asp.net 为ViewModel创建视图post返回具有空外键属性的ViewModel

Asp.net 为ViewModel创建视图post返回具有空外键属性的ViewModel,asp.net,asp.net-mvc-3,post,mvvm,viewmodel,Asp.net,Asp.net Mvc 3,Post,Mvvm,Viewmodel,我正在ASP.NET MVC3(我的第一个)中开发一个web应用程序,用于跟踪我所在工程公司的数据处理步骤 以下是一些域模型: 数据集: Partial Public MustInherit Class Dataset Public Property DatasetID As System.Guid Public Property Name As String Public Overridable Property ProcessDatasets As ICollect

我正在ASP.NET MVC3(我的第一个)中开发一个web应用程序,用于跟踪我所在工程公司的数据处理步骤

以下是一些域模型:

数据集:

Partial Public MustInherit Class Dataset
    Public Property DatasetID As System.Guid
    Public Property Name As String

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)
    Public Overridable Property DeliveryBatches As ICollection(Of DeliveryBatch) = New HashSet(Of DeliveryBatch)

End Class
Partial Public Class Process
    Public Property ProcessID As System.Guid
    Public Property Name As String
    Public Property Type As String
    Public Property Description As String
    Public Property SOP As String
    Public Property ProcessOrder As Nullable(Of Integer)

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)

End Class
Public Class ProcessStatusDataset

    Public Property ProcessDataset As ProcessDataset
    Public Property Datasets As IEnumerable(Of Dataset)

End Class
'
' GET: /ProcessDataset/Create

Function CreateProcessStatus(id As Guid) As ViewResult
    Dim processStatus As New ProcessStatusDataset
    processStatus.Datasets = db.Datasets.Where(Function(d) d.DatasetID = id)
    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name")
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name")
    Return View(processStatus)
End Function

'
' POST: /ProcessDataset/Create

<HttpPost()>
Function CreateProcessStatus(processstatusdataset As ProcessStatusDataset) As ActionResult
    If ModelState.IsValid Then
        For Each dataset In processstatusdataset.Datasets
            Dim processdataset As New ProcessDataset
            processdataset.ProcessID = processstatusdataset.ProcessDataset.ProcessID
            processdataset.OwnerID = processstatusdataset.ProcessDataset.OwnerID
            processdataset.Completed = processstatusdataset.ProcessDataset.Completed
            processdataset.Started = processstatusdataset.ProcessDataset.Started
            processdataset.DatasetID = dataset.DatasetID
            db.ProcessDatasets.Add(processdataset)
        Next
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name", processstatusdataset.ProcessDataset.ProcessID)
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name", processstatusdataset.ProcessDataset.OwnerID)
    Return View(processstatusdataset)
@ModelType ProductionDataTrackingMVC.ProcessStatusDataset
@Code
    ViewData("Title") = "Add New Process to Datasets"
End Code
<h2>
    Add New Process to Datasets</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@Using Html.BeginForm("CreateProcessStatus","ProcessDataset")
    @Html.ValidationSummary(True)
    @<fieldset>
        <legend>Process Status</legend>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Process):
        </div>
        <div class="editor-field">
            @Html.DropDownList("ProcessID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.ProcessID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.ProcessOwner):
        </div>
        <div class="editor-field">
            @Html.DropDownList("OwnerID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.OwnerID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Started):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Started)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Started)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Completed):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Completed)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Completed)
        </div>
        <br />
        <div>
            <table>
                <tr>
                    <th>
                        Dataset Type
                    </th>
                    <th>
                        @Html.LabelForPascalCase(Function(model) model.Datasets.FirstOrDefault().Name)
                    </th>
                </tr>
    @For Each item In Model.Datasets
        Dim currentItem = item
                @<tr>
                    <td>
                        @currentItem.GetType().BaseType.Name
                    </td>
                    <td>
                        @Html.DisplayFor(Function(modelItem) currentItem.Name)
                    </td>
                </tr>
    Next
            </table>
        </div>
        <p>
            <input type="submit" value="Add New Process Status" />
        </p>
    </fieldset>
End Using
<div>
    @Html.ActionLink("Back to Process Status Datasets List", "Index")
</div>
过程:

Partial Public MustInherit Class Dataset
    Public Property DatasetID As System.Guid
    Public Property Name As String

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)
    Public Overridable Property DeliveryBatches As ICollection(Of DeliveryBatch) = New HashSet(Of DeliveryBatch)

End Class
Partial Public Class Process
    Public Property ProcessID As System.Guid
    Public Property Name As String
    Public Property Type As String
    Public Property Description As String
    Public Property SOP As String
    Public Property ProcessOrder As Nullable(Of Integer)

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)

End Class
Public Class ProcessStatusDataset

    Public Property ProcessDataset As ProcessDataset
    Public Property Datasets As IEnumerable(Of Dataset)

End Class
'
' GET: /ProcessDataset/Create

Function CreateProcessStatus(id As Guid) As ViewResult
    Dim processStatus As New ProcessStatusDataset
    processStatus.Datasets = db.Datasets.Where(Function(d) d.DatasetID = id)
    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name")
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name")
    Return View(processStatus)
End Function

'
' POST: /ProcessDataset/Create

<HttpPost()>
Function CreateProcessStatus(processstatusdataset As ProcessStatusDataset) As ActionResult
    If ModelState.IsValid Then
        For Each dataset In processstatusdataset.Datasets
            Dim processdataset As New ProcessDataset
            processdataset.ProcessID = processstatusdataset.ProcessDataset.ProcessID
            processdataset.OwnerID = processstatusdataset.ProcessDataset.OwnerID
            processdataset.Completed = processstatusdataset.ProcessDataset.Completed
            processdataset.Started = processstatusdataset.ProcessDataset.Started
            processdataset.DatasetID = dataset.DatasetID
            db.ProcessDatasets.Add(processdataset)
        Next
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name", processstatusdataset.ProcessDataset.ProcessID)
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name", processstatusdataset.ProcessDataset.OwnerID)
    Return View(processstatusdataset)
@ModelType ProductionDataTrackingMVC.ProcessStatusDataset
@Code
    ViewData("Title") = "Add New Process to Datasets"
End Code
<h2>
    Add New Process to Datasets</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@Using Html.BeginForm("CreateProcessStatus","ProcessDataset")
    @Html.ValidationSummary(True)
    @<fieldset>
        <legend>Process Status</legend>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Process):
        </div>
        <div class="editor-field">
            @Html.DropDownList("ProcessID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.ProcessID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.ProcessOwner):
        </div>
        <div class="editor-field">
            @Html.DropDownList("OwnerID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.OwnerID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Started):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Started)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Started)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Completed):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Completed)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Completed)
        </div>
        <br />
        <div>
            <table>
                <tr>
                    <th>
                        Dataset Type
                    </th>
                    <th>
                        @Html.LabelForPascalCase(Function(model) model.Datasets.FirstOrDefault().Name)
                    </th>
                </tr>
    @For Each item In Model.Datasets
        Dim currentItem = item
                @<tr>
                    <td>
                        @currentItem.GetType().BaseType.Name
                    </td>
                    <td>
                        @Html.DisplayFor(Function(modelItem) currentItem.Name)
                    </td>
                </tr>
    Next
            </table>
        </div>
        <p>
            <input type="submit" value="Add New Process Status" />
        </p>
    </fieldset>
End Using
<div>
    @Html.ActionLink("Back to Process Status Datasets List", "Index")
</div>
ProcessDataset:(属性联接表)

我的目标是从数据集的索引或详细信息视图(使用域模型)中选择一个或多个数据集,然后单击链接
将新流程添加到数据集
,这将打开此所需的创建视图。创建视图创建的任何ProcessDataSet都将自动引用所选数据集,而用户无需从列表中选择它们

下面是我为ProcessDataset创建的ViewModel

ProcessStatusDataset:

Partial Public MustInherit Class Dataset
    Public Property DatasetID As System.Guid
    Public Property Name As String

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)
    Public Overridable Property DeliveryBatches As ICollection(Of DeliveryBatch) = New HashSet(Of DeliveryBatch)

End Class
Partial Public Class Process
    Public Property ProcessID As System.Guid
    Public Property Name As String
    Public Property Type As String
    Public Property Description As String
    Public Property SOP As String
    Public Property ProcessOrder As Nullable(Of Integer)

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)

End Class
Public Class ProcessStatusDataset

    Public Property ProcessDataset As ProcessDataset
    Public Property Datasets As IEnumerable(Of Dataset)

End Class
'
' GET: /ProcessDataset/Create

Function CreateProcessStatus(id As Guid) As ViewResult
    Dim processStatus As New ProcessStatusDataset
    processStatus.Datasets = db.Datasets.Where(Function(d) d.DatasetID = id)
    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name")
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name")
    Return View(processStatus)
End Function

'
' POST: /ProcessDataset/Create

<HttpPost()>
Function CreateProcessStatus(processstatusdataset As ProcessStatusDataset) As ActionResult
    If ModelState.IsValid Then
        For Each dataset In processstatusdataset.Datasets
            Dim processdataset As New ProcessDataset
            processdataset.ProcessID = processstatusdataset.ProcessDataset.ProcessID
            processdataset.OwnerID = processstatusdataset.ProcessDataset.OwnerID
            processdataset.Completed = processstatusdataset.ProcessDataset.Completed
            processdataset.Started = processstatusdataset.ProcessDataset.Started
            processdataset.DatasetID = dataset.DatasetID
            db.ProcessDatasets.Add(processdataset)
        Next
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name", processstatusdataset.ProcessDataset.ProcessID)
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name", processstatusdataset.ProcessDataset.OwnerID)
    Return View(processstatusdataset)
@ModelType ProductionDataTrackingMVC.ProcessStatusDataset
@Code
    ViewData("Title") = "Add New Process to Datasets"
End Code
<h2>
    Add New Process to Datasets</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@Using Html.BeginForm("CreateProcessStatus","ProcessDataset")
    @Html.ValidationSummary(True)
    @<fieldset>
        <legend>Process Status</legend>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Process):
        </div>
        <div class="editor-field">
            @Html.DropDownList("ProcessID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.ProcessID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.ProcessOwner):
        </div>
        <div class="editor-field">
            @Html.DropDownList("OwnerID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.OwnerID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Started):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Started)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Started)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Completed):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Completed)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Completed)
        </div>
        <br />
        <div>
            <table>
                <tr>
                    <th>
                        Dataset Type
                    </th>
                    <th>
                        @Html.LabelForPascalCase(Function(model) model.Datasets.FirstOrDefault().Name)
                    </th>
                </tr>
    @For Each item In Model.Datasets
        Dim currentItem = item
                @<tr>
                    <td>
                        @currentItem.GetType().BaseType.Name
                    </td>
                    <td>
                        @Html.DisplayFor(Function(modelItem) currentItem.Name)
                    </td>
                </tr>
    Next
            </table>
        </div>
        <p>
            <input type="submit" value="Add New Process Status" />
        </p>
    </fieldset>
End Using
<div>
    @Html.ActionLink("Back to Process Status Datasets List", "Index")
</div>
ProcessDatasetController中的控制器方法:

Partial Public MustInherit Class Dataset
    Public Property DatasetID As System.Guid
    Public Property Name As String

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)
    Public Overridable Property DeliveryBatches As ICollection(Of DeliveryBatch) = New HashSet(Of DeliveryBatch)

End Class
Partial Public Class Process
    Public Property ProcessID As System.Guid
    Public Property Name As String
    Public Property Type As String
    Public Property Description As String
    Public Property SOP As String
    Public Property ProcessOrder As Nullable(Of Integer)

    Public Overridable Property ProcessDatasets As ICollection(Of ProcessDataset) = New HashSet(Of ProcessDataset)

End Class
Public Class ProcessStatusDataset

    Public Property ProcessDataset As ProcessDataset
    Public Property Datasets As IEnumerable(Of Dataset)

End Class
'
' GET: /ProcessDataset/Create

Function CreateProcessStatus(id As Guid) As ViewResult
    Dim processStatus As New ProcessStatusDataset
    processStatus.Datasets = db.Datasets.Where(Function(d) d.DatasetID = id)
    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name")
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name")
    Return View(processStatus)
End Function

'
' POST: /ProcessDataset/Create

<HttpPost()>
Function CreateProcessStatus(processstatusdataset As ProcessStatusDataset) As ActionResult
    If ModelState.IsValid Then
        For Each dataset In processstatusdataset.Datasets
            Dim processdataset As New ProcessDataset
            processdataset.ProcessID = processstatusdataset.ProcessDataset.ProcessID
            processdataset.OwnerID = processstatusdataset.ProcessDataset.OwnerID
            processdataset.Completed = processstatusdataset.ProcessDataset.Completed
            processdataset.Started = processstatusdataset.ProcessDataset.Started
            processdataset.DatasetID = dataset.DatasetID
            db.ProcessDatasets.Add(processdataset)
        Next
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    ViewBag.ProcessID = New SelectList(db.Processes, "ProcessID", "Name", processstatusdataset.ProcessDataset.ProcessID)
    ViewBag.OwnerID = New SelectList(db.ProcessOwners, "ProcessOwnerID", "Name", processstatusdataset.ProcessDataset.OwnerID)
    Return View(processstatusdataset)
@ModelType ProductionDataTrackingMVC.ProcessStatusDataset
@Code
    ViewData("Title") = "Add New Process to Datasets"
End Code
<h2>
    Add New Process to Datasets</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@Using Html.BeginForm("CreateProcessStatus","ProcessDataset")
    @Html.ValidationSummary(True)
    @<fieldset>
        <legend>Process Status</legend>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Process):
        </div>
        <div class="editor-field">
            @Html.DropDownList("ProcessID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.ProcessID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.ProcessOwner):
        </div>
        <div class="editor-field">
            @Html.DropDownList("OwnerID", String.Empty)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.OwnerID)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Started):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Started)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Started)
        </div>
        <div class="editor-label">
            @Html.LabelForPascalCase(Function(model) model.ProcessDataset.Completed):
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ProcessDataset.Completed)
            @Html.ValidationMessageFor(Function(model) model.ProcessDataset.Completed)
        </div>
        <br />
        <div>
            <table>
                <tr>
                    <th>
                        Dataset Type
                    </th>
                    <th>
                        @Html.LabelForPascalCase(Function(model) model.Datasets.FirstOrDefault().Name)
                    </th>
                </tr>
    @For Each item In Model.Datasets
        Dim currentItem = item
                @<tr>
                    <td>
                        @currentItem.GetType().BaseType.Name
                    </td>
                    <td>
                        @Html.DisplayFor(Function(modelItem) currentItem.Name)
                    </td>
                </tr>
    Next
            </table>
        </div>
        <p>
            <input type="submit" value="Add New Process Status" />
        </p>
    </fieldset>
End Using
<div>
    @Html.ActionLink("Back to Process Status Datasets List", "Index")
</div>
其中链接末端的Guid是在
数据集
详细视图中选择的单个
数据集
的ID


谁能给我指一下正确的方向吗。我一直在搜索谷歌,但运气不佳。

下拉列表

我认为这行不通:

相反,您应该尝试以下方法:

这应该让model binder(如果你不知道这个概念,你可能想用谷歌搜索一下)发挥它的魔力。否则,只需将
HttpPost
操作方法的返回类型更改为
FormCollection
,并检查键以检查您从帖子中带回的内容

数据集问题


我不认为您将任何html表单字段设置为希望在您的帖子中看到某些内容。

我不确定我是否理解您在这里的建议。你在回答的“数据集问题”部分中的意思是什么?你说在你的post action
数据集
属性是
Nothing
,这是因为没有任何字段在html表单中存储此类信息。你是否检查了我提到的
FormCollection
方法,这可能有助于理解帖子结果的变化。我理解你的意思。我假设,因为我正在将一个模型传递到具有数据集的视图中,所以该视图将使用添加的数据传递回同一个模型。视图似乎创建了一个新模型以传回?我将如何使数据集与发布回控制器的模型保持一致?顺便说一句,您的下拉建议有效,谢谢。在您的案例场景中,我将使用DatasetId设置一个隐藏输入,因为它是您的帖子上似乎需要的唯一属性。如果编码正确,视图中应该只有一行添加了隐藏字段,并且Post操作应该像现在一样工作。我把这个留给你,兄弟,你很接近!也要读一下模型活页夹,这很重要。