IModelBinder如何维护模型的当前状态

时间:2012-01-19 20:26:11

标签: asp.net-mvc-3

我正在使用MVC3并使用自定义ModelBinder传递我构建的ProducerListViewModel

以下是我目前使用的控制器代码:

    Function Filter(user As UserModel, viewModel As ProducerListViewModel) As ActionResult

        If IsNothing(viewModel) Then
            viewModel = New ProducerListViewModel(user)
        End If

        Return View(viewModel)

    End Function

    <HttpPost()> _
    Function Filter(user As UserModel, viewModel As ProducerListViewModel, <Bind(Prefix:="Filter")> filterModel As ProducerFilterModel) As ActionResult
        'update the filter in the view model and send off to the list method
        viewModel.Filter = filterModel
        Return RedirectToAction("List")
    End Function

    Function List(user As UserModel, viewModel As ProducerListViewModel) As ActionResult

        Return Nothing

    End Function

这是自定义ModelBinder

中绑定的模型的代码
<Serializable()> _
<ModelBinder(GetType(ProducerListViewBinder))> _
Public Class ProducerListViewModel

    <XmlIgnore()> _
    Public Property Producers As IEnumerable(Of ProducerModel)
    Public Property PagingInfo As New PagingInfoModel("Load More Producers")
    Public Property Filter As New ProducerFilterModel()

    Public Sub New(user As UserModel)
        Me.Filter = ProducerFilterBL.Retrieve(user)
    End Sub

End Class

以下是Binder的代码:

Public Class ProducerListViewBinder
    Implements IModelBinder

    Private Const __sessionKey As String = "ProducerListView"

    Public Function BindModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As Object Implements IModelBinder.BindModel

        Dim filter As ProducerListViewModel

        'check to see if the filter exists in session
        If IsNothing(controllerContext.HttpContext.Session(ProducerListViewBinder.__sessionKey)) Then
            'load existing filter for user and store for later retrieval
            Dim user As UserModel = UserBL.RetrieveUser()
            filter = New ProducerListViewModel(user)
            ProducerListViewBinder.SetItem(filter)
        Else
            filter = CType(controllerContext.HttpContext.Session(ProducerListViewBinder.__sessionKey), ProducerListViewModel)
        End If

        Return filter

    End Function

End Class

流程如下:

  1. 用户导航到过滤页面,点击第一个操作(过滤器)
  2. 用户对过滤器进行更改并提交页面,点击第二个操作(过滤w / Post)
  3. 具有Post操作的过滤器使用模型绑定(第三个参数filterModel As ProducerFilterModel)接收更新的过滤器,更新ProducerListFilterModel,并重定向到List操作
  4. 一切正常,但这是我的问题:

    为什么List操作在ProducerFilterModel内有ProducerListViewModel的更新版本?

    我喜欢它如此完美,我只是想知道它为什么会起作用。

1 个答案:

答案 0 :(得分:1)

现在您已经显示了模型绑定器的代码,一切都非常清楚。此模型绑定器将ProducerListViewModel实例存储到会话中,这使得它可以在重定向中存活。

第一次点击POST Filter操作时,会话中没有任何内容,因此您的自定义模型绑定器会执行一些数据库查找或检索值:

Dim user As UserModel = UserBL.RetrieveUser()
filter = New ProducerListViewModel(user)
ProducerListViewBinder.SetItem(filter)

然后将此值存储到会话中。我想这是ProducerListViewBinder.SetItem做这项工作。不幸的是你没有显示它的代码,但我准备下注5美元这是它的作用。

然后执行Filter操作,最后重定向到以List为参数的ProducerListViewModel操作。所以你的自定义模型绑定器再次启动,但这次它找到它先前存储在会话中的实例,它只是从那里返回它。

所以这里没有魔力。它只是使用ASP.NET会话,以便在重定向之间保留值。