Datatables.mvc (VB.NET版本)

出自 ProgWiki
前往: 導覽搜尋

datatables.mvc (VB.NET版本)DataTables的Server端應用。

  • 由於C#與VB.NET的差異,所以略做修改

原始出處

ASP.NET MVC (C#)

檔案

Column.vb

Imports Microsoft.VisualBasic
 
Namespace DataTables.Mvc
 
    ''' <summary>
    ''' Represents a DataTables column for server-side parsing and work.
    ''' </summary>
    Public Class Column
 
        ''' <summary>
        ''' Gets the data component (bind property name).
        ''' </summary>
        Public Property Data() As String
 
        ''' <summary>
        ''' Get's the name component (if any provided on client-side script).
        ''' </summary>
        Public Property Name() As String
 
        ''' <summary>
        ''' Indicates if the column is searchable or not.
        ''' </summary>
        Public Property Searchable() As Boolean
 
        ''' <summary>
        ''' Indicates if the column is orderable or not.
        ''' </summary>
        Public Property Orderable() As Boolean
 
        ''' <summary>
        ''' Gets the search component for the column.
        ''' </summary>
        Public Property Search() As Search
 
        ''' <summary>
        ''' Indicates if the current column should be ordered on server-side or not.
        ''' </summary>
        Public ReadOnly Property IsOrdered() As Boolean
            Get
                Return OrderNumber <> -1
            End Get
        End Property
 
        ''' <summary>
        ''' Indicates the column' position on the ordering (multi-column ordering).
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property OrderNumber() As Integer
 
        ''' <summary>
        ''' Indicates the column's sort direction.
        ''' </summary>
        Public Property SortDirection() As OrderDirection
 
        ''' <summary>
        ''' Sets the columns ordering.
        ''' </summary>
        ''' <param name="orderNumber">The column's position on the ordering (multi-column ordering).</param>
        ''' <param name="orderDirection">The column's sort direction.</param>
        ''' <exception cref="System.ArgumentException">Thrown if the provided orderDirection is not valid.</exception>
        Public Sub SetColumnOrdering(orderNumber As Integer, orderDirection As String)
            Me.OrderNumber = orderNumber
 
            Select Case orderDirection.ToLower()
                Case "asc"
                    Me.SortDirection = Column.OrderDirection.Ascendant
                Case "desc"
                    Me.SortDirection = Column.OrderDirection.Descendant
                Case Else
                    Throw New ArgumentException("The provided ordering direction was not valid. Valid values must be 'asc' or 'desc' only.")
            End Select
        End Sub
 
        ''' <summary>
        ''' Creates a new DataTables column.
        ''' </summary>
        ''' <param name="data">The data component (bind property name).</param>
        ''' <param name="name">The name of the column (if provided).</param>
        ''' <param name="searchable">True if the column allows searching, false otherwise.</param>
        ''' <param name="orderable">True if the column allows ordering, false otherwise.</param>
        ''' <param name="searchValue">The searched value for the column, or an empty string.</param>
        ''' <param name="isRegexValue">True if the search value is a regex value, false otherwise.</param>
        Public Sub New(data As String, name As String, searchable As Boolean, orderable As Boolean, searchValue As String, isRegexValue As Boolean)
            Me.Data = data
            Me.Name = name
            Me.Searchable = searchable
            Me.Orderable = orderable
            Me.Search = New Search(searchValue, isRegexValue)
 
            ' Default - indicates that the column should not be ordered on server-side.
            Me.OrderNumber = -1
        End Sub
 
        ''' <summary>
        ''' Defines order directions for proper use.
        ''' </summary>
        Public Enum OrderDirection
            ''' <summary>
            ''' Represents an ascendant (A-Z) ordering.
            ''' </summary>
            Ascendant = 0
            ''' <summary>
            ''' Represents a descendant (Z-A) ordering.
            ''' </summary>
            Descendant = 1
        End Enum
 
    End Class
End Namespace

ColumnCollection.vb

Imports Microsoft.VisualBasic
Imports System.Collections
Imports System.Collections.Generic
 
Namespace DataTables.Mvc
 
    ''' <summary>
    ''' Represents a read-only DataTables column collection.
    ''' </summary>
    Public Class ColumnCollection
        Implements IEnumerable(Of Column)
 
 
        ''' <summary>
        ''' For internal use only.
        ''' Stores data.
        ''' </summary>
        Private Data As IReadOnlyList(Of Column)
 
        ''' <summary>
        ''' Created a new ReadOnlyColumnCollection with predefined data.
        ''' </summary>
        ''' <param name="columns">The column collection from DataTables.</param>
        Public Sub New(columns As IEnumerable(Of Column))
            If columns Is Nothing Then
                Throw New ArgumentNullException("The provided column collection cannot be null", "columns")
            End If
            Data = columns.ToList().AsReadOnly()
        End Sub
 
        ''' <summary>
        ''' Get sorted columns on client-side already on the same order as the client requested.
        ''' The method checks if the column is bound and if it's ordered on client-side.
        ''' </summary>
        ''' <returns>The ordered enumeration of sorted columns.</returns>
        Public Function GetSortedColumns() As IOrderedEnumerable(Of Column)
            Return Data _
                .Where(Function(_column) Not String.IsNullOrWhiteSpace(_column.Data) AndAlso _column.IsOrdered) _
                .OrderBy(Function(_c) _c.OrderNumber)
        End Function
 
        ''' <summary>
        ''' Get filtered columns on client-side.
        ''' The method checks if the column is bound and if the search has a value.
        ''' </summary>
        ''' <returns>The enumeration of filtered columns.</returns>
        Public Function GetFilteredColumns() As IEnumerable(Of Column)
            Return Data _
                .Where(Function(_column) Not String.IsNullOrWhiteSpace(_column.Data) AndAlso _column.Searchable AndAlso Not String.IsNullOrWhiteSpace(_column.Search.Value))
        End Function
 
        ''' <summary>
        ''' Returns the enumerable element as defined on IEnumerable.
        ''' </summary>
        Public Function GetEnumerator() As IEnumerator(Of Column) Implements IEnumerable(Of Column).GetEnumerator
            Return Data.GetEnumerator()
        End Function
 
        ''' <summary>
        ''' Returns the enumerable element as defined on IEnumerable.
        ''' </summary>
        ''' <returns>The enumerable element to iterate through data.</returns>
        Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
            'Return DirectCast(Data, System.Collections.IEnumerable).GetEnumerator()
            Return Data.GetEnumerator()
        End Function
 
    End Class
End Namespace

DataTablesBinder.vb

Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.Web.Mvc
 
Namespace DataTables.Mvc
 
    ''' <summary>
    ''' Defines a DataTables binder to bind a model with the request parameters from DataTables.
    ''' </summary>
    Public Class DataTablesBinder
        Implements IModelBinder
 
        ''' <summary>
        ''' Formatting to retrieve data for each column.
        ''' </summary>
        Protected ReadOnly COLUMN_DATA_FORMATTING As String = "columns[{0}][data]"
 
        ''' <summary>
        ''' Formatting to retrieve name for each column.
        ''' </summary>
        Protected ReadOnly COLUMN_NAME_FORMATTING As String = "columns[{0}][name]"
 
        ''' <summary>
        ''' Formatting to retrieve searchable indicator for each column.
        ''' </summary>
 
        Protected ReadOnly COLUMN_SEARCHABLE_FORMATTING As String = "columns[{0}][searchable]"
        ''' <summary>
        ''' Formatting to retrieve orderable indicator for each column.
        ''' </summary>
        Protected ReadOnly COLUMN_ORDERABLE_FORMATTING As String = "columns[{0}][orderable]"
 
        ''' <summary>
        ''' Formatting to retrieve search value for each column.
        ''' </summary>
        Protected ReadOnly COLUMN_SEARCH_VALUE_FORMATTING As String = "columns[{0}][search][value]"
 
        ''' <summary>
        ''' Formatting to retrieve search regex indicator for each column.
        ''' </summary>
        Protected ReadOnly COLUMN_SEARCH_REGEX_FORMATTING As String = "columns[{0}][search][regex]"
 
        ''' <summary>
        ''' Formatting to retrieve ordered columns.
        ''' </summary>
        Protected ReadOnly ORDER_COLUMN_FORMATTING As String = "order[{0}][column]"
 
        ''' <summary>
        ''' Formatting to retrieve columns order direction.
        ''' </summary>
        Protected ReadOnly ORDER_DIRECTION_FORMATTING As String = "order[{0}][dir]"
 
        ''' <summary>
        ''' Binds a new model with the DataTables request parameters.
        ''' </summary>
        ''' <param name="controllerContext"></param>
        ''' <param name="bindingContext"></param>
        ''' <returns></returns>
        Public Function BindModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As Object Implements IModelBinder.BindModel
            Dim request = controllerContext.RequestContext.HttpContext.Request
            Dim requestMethod = request.HttpMethod.ToLower()
 
            Dim model = New DataTablesRequest()
 
            ' We could use the `bindingContext.ValueProvider.GetValue("key")` approach but
            ' directly accessing the HttpValueCollection will improve performance if you have
            ' more than 2 registered value providers.
            Dim requestParameters As NameValueCollection = ResolveNameValueCollection(request)
 
            ' Populates the model with the draw count from DataTables.
            model.Draw = requestParameters("draw")
 
            ' Populates the model with page info (server-side paging).
            model.Start = requestParameters("start")
            model.Length = requestParameters("length")
 
            ' Populates the model with search (global search).
            Dim searchValue As String = requestParameters("search[value]")
            Dim searchRegex As Boolean = requestParameters("search[regex]")
            model.Search = New Search(searchValue, searchRegex)
 
            ' Get's the column collection from the request parameters.
            Dim columns = GetColumns(requestParameters)
 
            ' Parse column ordering.
            ParseColumnOrdering(requestParameters, columns)
 
            ' Attach columns into the model.
            model.SetColumns(columns)
 
            ' Returns the filled model.
            Return DirectCast(model, IDataTablesRequest)
        End Function
 
        ''' <summary>
        ''' Resolves the NameValueCollection from the request.
        ''' Default implementation supports only GET and POST methods.
        ''' You may override this method to support other HTTP verbs.
        ''' </summary>
        ''' <param name="request">The HttpRequestBase object that represents the MVC request.</param>
        ''' <returns>The NameValueCollection with request variables.</returns>
        Protected Overridable Function ResolveNameValueCollection(request As HttpRequestBase) As NameValueCollection
            Select Case request.HttpMethod.ToLower()
                Case "get"
                    Return request.QueryString
                Case "post"
                    Return request.Form
                Case Else
                    Throw New ArgumentException(String.Format("The provided HTTP method ({0}) is not a valid method to use with DataTablesBinder. Please, use HTTP GET or POST methods only.", request.HttpMethod), "method")
            End Select
        End Function
 
 
        ''' <summary>
        ''' Return's the column collection from the request values.
        ''' This method is provided as an option for you to override the default behavior and add aditional
        ''' check or change the returned value.
        ''' </summary>
        ''' <param name="collection">The request value collection.</param>
        ''' <returns>The collumn collection or an empty list. For default behavior, do not return null!</returns>
        Protected Overridable Function GetColumns(collection As NameValueCollection) As List(Of Column)
            Try
                Dim columns = New List(Of Column)()
 
                ' Loop through every request parameter to avoid missing any DataTable column.
                For i As Integer = 0 To collection.Count - 1
                    Dim columnData As String = collection(String.Format(COLUMN_DATA_FORMATTING, i))
                    Dim columnName As String = collection(String.Format(COLUMN_NAME_FORMATTING, i))
 
                    If columnData IsNot Nothing AndAlso columnName IsNot Nothing Then
                        Dim columnSearchable As Boolean = collection(String.Format(COLUMN_SEARCHABLE_FORMATTING, i))
                        Dim columnOrderable As Boolean = collection(String.Format(COLUMN_ORDERABLE_FORMATTING, i))
                        Dim columnSearchValue As Boolean = collection(String.Format(COLUMN_SEARCH_VALUE_FORMATTING, i))
                        Dim columnSearchRegex As Boolean = collection(String.Format(COLUMN_SEARCH_REGEX_FORMATTING, i))
 
                        columns.Add(New Column(columnData, columnName, columnSearchable, columnOrderable, columnSearchValue, columnSearchRegex))
                    Else
                        Exit For
                        ' Stops iterating because there's no more columns.
                    End If
                Next
 
                Return columns
            Catch
                ' Returns an empty column collection to avoid null exceptions.
                Return New List(Of Column)()
            End Try
        End Function
        ''' <summary>
        ''' Configure column's ordering.
        ''' This method is provided as an option for you to override the default behavior.
        ''' </summary>
        ''' <param name="collection">The request value collection.</param>
        ''' <param name="columns">The column collection as returned from GetColumns method.</param>
        Protected Overridable Sub ParseColumnOrdering(collection As NameValueCollection, columns As IEnumerable(Of Column))
            For i As Integer = 0 To collection.Count - 1
                Dim orderColumn As Integer = collection(String.Format(ORDER_COLUMN_FORMATTING, i))
                Dim orderDirection As String = collection(String.Format(ORDER_DIRECTION_FORMATTING, i))
 
                If orderColumn > -1 AndAlso orderDirection IsNot Nothing Then
                    columns.ElementAt(orderColumn).SetColumnOrdering(i, orderDirection)
                End If
            Next
        End Sub
    End Class
End Namespace

DataTablesJsonBinder.vb

Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Imports System.Web.Mvc
 
Namespace DataTables.Mvc
 
    ''' <summary>
    ''' Defines an abstract DataTables binder to bind a model with the JSON request from DataTables.
    ''' </summary>
    Public MustInherit Class DataTablesJsonBinder
        Implements IModelBinder
 
        ''' <summary>
        ''' Get's the JSON parameter name to retrieve data. 
        ''' You may override this to change to your parameter.
        ''' </summary>
        Protected Overridable ReadOnly Property JSON_PARAMETER_NAME() As String
            Get
                Return "json"
            End Get
        End Property
        ''' <summary>
        ''' Binds a new model with the DataTables request parameters.
        ''' </summary>
        ''' <param name="controllerContext"></param>
        ''' <param name="bindingContext"></param>
        ''' <returns></returns>
        Public Function BindModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As Object Implements IModelBinder.BindModel
            Dim request = controllerContext.RequestContext.HttpContext.Request
            Dim requestMethod = request.HttpMethod.ToLower()
            Dim requestType = request.ContentType
 
            ' If the request type does not contains "JSON", it's supposed not to be a JSON request so we skip.
            If Not IsJsonRequest(request) Then
                Throw New ArgumentException("You must provide a JSON request and set it's content type to match a JSON request content type.")
            End If
 
            ' Desserializes the JSON request using the .Net Json implementation.
            Return Deserialize(bindingContext.ValueProvider.GetValue(JSON_PARAMETER_NAME).AttemptedValue)
 
        End Function
 
 
        ''' <summary>
        ''' Checks if a request is a JsonRequest or not. 
        ''' You may override this to check for other values or indicators.
        ''' </summary>
        ''' <param name="request">The HttpRequestBase object representing the MVC request.</param>
        ''' <returns>True if the ContentType contains "json", False otherwise.</returns>
        Public Overridable Function IsJsonRequest(request As HttpRequestBase) As Boolean
            Return request.ContentType.ToLower().Contains("json")
        End Function
 
        ''' <summary>
        ''' When overriden, deserializes the JSON data into a DataTablesRequest object.
        ''' </summary>
        ''' <param name="jsonData">The JSON data to be deserialized.</param>
        ''' <returns>The DataTablesRequest object.</returns>
        Protected MustOverride Function Deserialize(jsonData As String) As IDataTablesRequest
 
    End Class
End Namespace

DataTablesResponse.vb

Imports Microsoft.VisualBasic
 
Namespace DataTables.Mvc
 
    ''' <summary>
    ''' Represents a server-side response for use with DataTables.
    ''' </summary>
    ''' <remarks>
    ''' Variable syntax matches DataTables names to avoid error and avoid aditional parse.
    ''' </remarks>
    Public Class DataTablesResponse
        ''' <summary>
        ''' Gets the draw counter for DataTables.
        ''' </summary>
        Public Property draw() As Integer
 
        ''' <summary>
        ''' Gets the data collection.
        ''' </summary>
        Public Property data() As IEnumerable
 
        ''' <summary>
        ''' Gets the total number of records (without filtering - total dataset).
        ''' </summary>
        Public Property recordsTotal() As Integer
 
        ''' <summary>
        ''' Gets the resulting number of records after filtering.
        ''' </summary>
        Public Property recordsFiltered() As Integer
 
        ''' <summary>
        ''' Creates a new DataTables response object with it's elements.
        ''' </summary>
        ''' <param name="draw">The draw counter as received from the DataTablesRequest.</param>
        ''' <param name="data">The data collection (data page).</param>
        ''' <param name="recordsFiltered">The resulting number of records after filtering.</param>
        ''' <param name="recordsTotal">The total number of records (total dataset).</param>
        Public Sub New(draw As Integer, data As IEnumerable, recordsFiltered As Integer, recordsTotal As Integer)
            Me.draw = draw
            Me.data = data
            Me.recordsFiltered = recordsFiltered
            Me.recordsTotal = recordsTotal
        End Sub
    End Class
End Namespace

IDataTablesRequest.vb

Imports Microsoft.VisualBasic
 
Namespace DataTables.Mvc
 
    ''' <summary>
    ''' Defines a server-side request for use with DataTables.
    ''' </summary>
    ''' <remarks>
    ''' Variable syntax does NOT match DataTables names because auto-mapping won't work anyway.
    ''' Use the DataTablesModelBinder or provide your own binder to bind your model with DataTables's request.
    ''' </remarks>
    Public Interface IDataTablesRequest
 
        ''' <summary>
        ''' Gets the draw counter from client-side to give back on the server's response.
        ''' </summary>
        Property Draw() As Integer
 
        ''' <summary>
        ''' Gets the start record number (count) for paging.
        ''' </summary>
        Property Start() As Integer
 
        ''' <summary>
        ''' Gets the length of the page (max records per page).
        ''' </summary>
        Property Length() As Integer
 
        ''' <summary>
        ''' Gets the global search pagameters.
        ''' </summary>
        Property Search() As Search
 
        ''' <summary>
        ''' Gets the read-only collection of client-side columns with their options and configs.
        ''' </summary>
        Property Columns() As ColumnCollection
    End Interface
 
    ''' <summary>
    ''' For internal use only.
    ''' Represents DataTables request parameters.
    ''' </summary>
    Class DataTablesRequest
        Implements IDataTablesRequest
 
        ''' <summary>
        ''' For internal use only.
        ''' Gets/Sets the draw counter from DataTables.
        ''' </summary>
        Public Property Draw() As Integer Implements IDataTablesRequest.Draw
 
        ''' <summary>
        ''' For internal use only.
        ''' Gets/Sets the start record number (jump) for paging.
        ''' </summary>
        Public Property Start() As Integer Implements IDataTablesRequest.Start
 
        ''' <summary>
        ''' For internal use only.
        ''' Gets/Sets the length of the page (paging).
        ''' </summary>
        Public Property Length() As Integer Implements IDataTablesRequest.Length
 
        ''' <summary>
        ''' For internal use only.
        ''' Gets/Sets the global search term.
        ''' </summary>
        Public Property Search() As Search Implements IDataTablesRequest.Search
 
        ''' <summary>
        ''' For internal use only.
        ''' Gets/Sets the column collection.
        ''' </summary>
        Public Property Columns() As ColumnCollection Implements IDataTablesRequest.Columns
 
        ''' <summary>
        ''' For internal use only.
        ''' Set the new columns on the mechanism.
        ''' </summary>
        ''' <param name="columns">The columns to be set.</param>
        Public Sub SetColumns(ByVal columns As IEnumerable(Of Column))
            columns = New ColumnCollection(columns)
        End Sub
 
    End Class
End Namespace

NameValueCollectionExtensions.vb

  • 不需要

Search.vb

Imports Microsoft.VisualBasic
 
Namespace DataTables.Mvc
 
    ''' <summary>
    ''' Stores parameters and configs from DataTables search engine.
    ''' </summary>
    Public Class Search
 
        ''' <summary>
        ''' Gets the value of the search.
        ''' </summary>
        Public Property Value() As String
 
        ''' <summary>
        ''' Indicates if the value of the search is a regex value or not.
        ''' </summary>
        Public Property IsRegexValue As Boolean
 
        ''' <summary>
        ''' Creates a new search values holder object.
        ''' </summary>
        ''' <param name="value">The value of the search.</param>
        ''' <param name="isRegexValue">True if the value is a regex value or false otherwise.</param>
        ''' <exception cref="System.ArgumentNullException">Thrown when the provided search value is null.</exception>
        Public Sub New(value As String, isRegexValue As Boolean)
            If value Is Nothing Then
                Throw New ArgumentNullException("value", "The value of the search cannot be null. If there's no search performed, provide an empty string.")
            End If
 
            Me.Value = value
            Me.IsRegexValue = isRegexValue
        End Sub
 
    End Class
End Namespace