question

AppDev-1530 avatar image
0 Votes"
AppDev-1530 asked YijingSun-MSFT commented

Not understanding Viewmodels in mvc I am using vb.net to see if it will help me understand it better

Hi All I am having trouble wrapping my heard around view models.
I have tried lots of tutorials to try to understand them and how to use them but nothing makes any since as there in nothing that shows you how to populate your database from the view model.

Not matter what language I use c sharp or VB.net the errors do not tell you how o fix the issue.

So my issue, I have a table in the database called CODE_OPINION_TBL

195295-image.png

The Create Form used a view model called : ViewModelClass_CodeOpinions

Here is the view model:

 Imports System.ComponentModel.DataAnnotations
 Imports BFR_LOCAL_DB
    
 Public Class ViewModelClass_CodeOpinions
    
    
    
     Public Property ID() As Integer
     Public Property Code_Reference() As String
     Public Property Chapter() As String
     Public Property Section() As String
     Public Property Response_Date() As Nullable(Of Date)
     Public Property Year() As String
     Public Property Status() As String
     Public Property Author() As String
     Public Property From() As String
     Public Property Locality() As String
     Public Property Description() As String
     Public Property Comments() As String
     Public Property Attachments() As String
    
     Public Property ATTACHMENT_LINK As String
    
     Public Property CODE_REF_REC_ID() As Integer
     'Public Property CODE_REF_ID() As String
    
     Public Property CODE_REF_ID As Nullable(Of Short)
    
     Public Property CODE_DESCRIPTION() As String
     Public Property CODE_REF_CAT() As String
    
     <Required>
     <DataType(DataType.Upload)>
     <Display(Name:="Select File")>
     Public Property files As HttpPostedFileBase
    
     Public Property FILE_ID As Integer
    
     <Display(Name:="Uploaded File")>
     Public Property FILE_NAME As String
     Public Property FILE_CONTENT As Byte()
     Public Property FILE_RECORD_ID As Integer
    
     Public Property CODE_REF_LIST() As List(Of CODE_REF_LOV_TBL)
    
     'Public Shared Widening Operator CType(v As ViewModelClass_CodeOpinions) As ViewModelClass_CodeOpinions
     '    Throw New NotImplementedException()
     'End Operator
 End Class




So when I change the controller to use the view model I get this error
195322-image.png

Severity Code Description Line
Error BC30311 Value of type 'ViewModelClass_CodeOpinions' cannot be converted to 'CODE_OPINIONS_TBL'. 212

Why does the program allow us to make view models if we can't use them or populate the database with them
I understand that they are just a mask like thing that allow you to setup you view to use data but I can't find any real world example that make use of them
in an understandable way.

If I leave this as CODE_OPINION_TBL it works fine even though the create views use the ViewModelClass_CodeOpinions
I just don't get it!






195285-image.png


dotnet-aspnet-mvc
image.png (41.8 KiB)
image.png (71.7 KiB)
image.png (109.7 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @AppDev-1530 ,
What is View model? ViewModels are used to shape multiple entities from one or more models into a single object. If we want to display more than one Model into a single View, we have to pass a ViewModel to that View, so that we can take benefits of both the models into a single object. So, we have to use ViewModel for better performance of sources.
So, about your error, if you want to manage the data, you must map the value from the database to your view model. However, I don't find any codes about this you post.
Best regards,
Yijing Sun

0 Votes 0 ·

1 Answer

cooldadtx avatar image
0 Votes"
cooldadtx answered cooldadtx edited

Viewmodels and DBs have nothing to do with each other. That's your first problem, you're trying to make them related. If you're using a viewmodel in your UI then you'll need to map your DB structures to it before passing it to the client and any models that come back from the client need to be converted back to whatever structure your data layer requires. You have to write this mapping yourself (or use a third party mapping tool like Automapper). For simple apps viewmodels may be overkill but as apps get larger viewmodels become very useful for maintainability.

Public Class CODE_OPINION_TBL
     Public Property ID() As Integer
     Public Property Chapter() As String
     Public Property Section() As String
End Class

Public Class ViewModelClass_CodeOpinions            
     Public Property ID() As Integer
     Public Property Chapter() As String
     Public Property Section() As String
End Class

' I prefer to use extension methods or mapper classes for conversion '
Public Shared Class CodeOpinionMapper
    <Extension()>
    Public Shared Function ToViewModel ( data As CODE_OPINION_TBL ) As ViewModelClass_CodeOpinions
       Dim model As new ViewModelClass_CodeOpinions
       With model
          .ID = data.ID
          .Chapter = data.Chapter
          .Section = data.Section
       End With
       Return model
    End Function

    <Extension()>
    Public Shared Function ToData ( model As ViewModelClass_CodeOpinions ) As CODE_OPINION_TBL
       Dim data As new CODE_OPINION_TBL
       With data
          .ID = model.ID
          .Chapter = model.Chapter
          .Section = model.Section
       End With
       Return data
    End Function
End Class

Dim data As New CODE_OPIONION_TBL
Dim model = data.ToViewModel()
Dim newData = model.ToData()


To be honest your specific example isn't complex enough to justify viewmodels so it is hard to see the benefit. The primary benefit of a viewmodel (or any mapping) is to reformat the underlying data into a structure that can be more easily processed by whoever you're handing it to (a view in this case). A more complex example may make this clearer.

Public Class StateOrProvince
    Public Property ID() As Integer
    Public Property Name() As String

    'Typically a data model has an ID and the corresponding object, if any '
    Public Property CountryID() As Integer
    Public Property Country() As Country
End Class

Public Class Country
    Public Property ID() As Integer
    Public Property Name() As String
End Class

Public Class StateOrProvinceViewModel
    Public Property ID() As Integer
    Public Property Name() As String

    'Flatten country information '
    Public Property CountryId() As Integer
    Public Property CountryName() As String
End Class

Public Shared Class StateOrProvinceMapper
    <Extension()>
    Public Shared Function ToViewModel ( state As StateOrProvince ) As StateOrProvinceViewModel
       Dim model As New StateOrProvinceViewModel()
       With model
           .ID = state.ID
           .Name = state.Name
       End With

       If state.Country Is Not Nothing Then
          model.CountryID = state.Country.ID
          model.CountryName = state.Country.Name.ToUpperCase()
       End If

       Return model
    End Function

    <Extension()>
    Public Shared Function ToData ( model As StateOrProvinceViewModel ) As StateOrProvince
       Dim data As New StateOrProvince
       With data
          .ID = model.ID
          .Name = model.Name
          .CountryID = model.CountryID
       End With

       ' Often we do not need related objects when going back to DB so leave the Country off... '
       Return data
    End Function
End Class










5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.