我在ASP.Net MVC 4中遇到以下奇怪的问题:
我在视图上有一个表单,处理表单提交的控制器。我第一次将表单提交给控制器如果存在验证问题,我想重新显示表单,以便用户可以纠正问题。如果用户然后更正了验证问题并尝试将表单第二次提交给同一个控制器,那么这就是问题开始发生的地方。就好像第一次提交的整个视图以某种方式被缓存一样,因此第一次提交之后的每个后续提交都不会从表单提交当前数据,而只是从第一次提交中重新提交数据。
我应该提到的一件事是视图中的表单字段不是基于模型中的静态字段。相反,字段是动态的,字段名称和字段值存储在模型内的数组/列表中。没有理由我不应该这样做,但值得一提,因为它可能在这个问题上发挥作用。
我的想法是表单上的字段值是根据字段名称缓存的,所以作为一种解决方法,我想在每次在新提交后重新显示表单时更改字段名称。但是,即使我更改了表单中的字段名称,当我检查源时,字段名称也不会更改。他们仍然反映旧名称。
我还发现,当第二次提交表单时,传递给控制器的模型是第一次提交时的模型状态,而不是当前提交的模型状态。我重新验证了重新显示视图时模型是否正确,但这似乎并不重要。传递给控制器的模型仍然是第一次提交时的模型,而不是视图在生成时所基于的模型。
所以有不必要的缓存,但我不明白为什么或如何发生。任何人都可以帮我指导解决方案吗?
View Follows的重要代码:
@Using Html.BeginForm("Action", "NewDocument", Model, FormMethod.Post, New With {.id = "newdocument-form", .autocomplete = "off"})
@<ul data-role="listview" data-inset="false" id="indexcriteria">
@For i = 0 To Model.IndexFieldCount() - 1
@<li>
<input type="text" name="@Model.FieldNameAtIndex(i)" value="@Model.FieldValueAtIndex(i)"/>
</li>
Next
</ul>
End Using
以下是处理提交的控制器操作:
<HttpPost()> _
<HttpParamAction()> _
<NoCache> _
Function Upload(ByVal model As MaxDocument, formcollection As FormCollection) As ActionResult
Dim sCriteria As String = ""
Dim nKeyIndex As Integer = 0
Dim nFieldIndex As Integer = -1
Dim sFieldValue As String = ""
Dim vrl As List(Of MaxServerLib.ValidationResult) = Nothing
Try
' Build sCriteria from the submitted formcollection
model.GetFileCabinetFieldList()
For nFieldIndex = 0 To (model.IndexFieldCount - 1)
sFieldValue = ""
If nFieldIndex > 0 Then
sCriteria += "~"
End If
Dim fcf As MaxServerLib.FileCabinetField = model.criterionAtIndex(nFieldIndex)
' Get the field value corresponding to this field
For Each oKey As Object In formcollection.AllKeys
If oKey.ToString = fcf.sFieldName Then
sFieldValue = formcollection(oKey.ToString)
Exit For
End If
Next
sCriteria += sFieldValue
Next
If sCriteria = "" Then sCriteria = "[BlankIndex]"
' Set the criteria property of the model, which will be used for both field validation and document export.
model.Criteria = sCriteria
' First thing we do is to perform valiation of the criteria
model.ValidateFieldValues()
If Not model.AllFieldValuesValid() Then
' Handle case where one or more field values are invalid.
' In this case we want to redisplay the form but show an error message listing the invalid fields
model.HasAttemptedUpload = True
model.Submitted = model.Submitted + 1
' Set tempData before redirect:
TempData("MaxDocument") = model
Return RedirectToAction("Index")
Else
' All field values are valid, now attempt to add the document
...
Else
' Document export failed for some reason
' ModelState.AddModelError("", model.LastError)
Return View(model)
End If
End If
Catch ex As Exception
System.Diagnostics.Debugger.Break()
End Try
'End If
' If we got this far, something failed, redisplay form
Return View(model)
End Function
这是控制器动作,它处理视图的显示:
Function Index(ByVal sMaxUrl As String, ByVal sDataSource As String, ByVal sUserName As String, ByVal sPassword As String) As ActionResult
' Picked up after redirect:
Dim md As MaxDocument = TempData("MaxDocument")
' Determine if the session timed out
If (DateTime.Now - md.LastCall).Minutes < SESSION_TIMEOUT_LENGTH Then
md.GetFileCabinetFieldList()
md.SetFieldValueList()
md.InitValidationResults()
' md.ShowMsg = sShowMsg
Return View(md)
Else
Return RedirectToAction("Login", "MaxLogin", New With {.sMaxUrl = sMaxUrl, .sDataSource = sDataSource, .sUserName = sUserName, .sPassword = sPassword, .sShowMsg = "Session Expired"})
End If
End Function
正如您在上面所看到的,当我的自定义表单验证从第一次提交失败时,我正在调用控制器索引操作以使用提交操作处理程序中的相同模型重新显示表单。
编辑:
我仍然没有解决这个问题,但下面的句子似乎最准确地描述了正在发生的事情:
浏览器似乎已缓存上一个(第一个)帖子操作,因此它会呈现第一个帖子的缓存结果,而不是处理控制器操作中的后续帖子。这对任何人都有意义吗?
此外,我在此表单上有两个提交按钮,并使用HttpParamAction()根据提交按钮的名称确定要转到哪个控制器操作。这可能以任何方式涉及这个问题吗?