The best way to bin the ownership of a ViewModel in post

0

Good morning,

The idea is the following: I have a project in ASP.NET 4.6.2 following the MVVM pattern, I have my ViewModel class that represents the page and one of the properties of that ViewModel is an object that has another object as its property. Step to code what is written:

public class AlumnoViewModel : BaseViewModel
{
    public List<AlumnoModel> Alumnos { get; set; }
    public AlumnoModel SearchEntity { get; set; }
    public AlumnoModel AddEntity { get; set; }

    public int TurnoId { get; set; }
    public int CarreraId { get; set; }

    public IEnumerable<SelectListItem> Carreras { get; set; }
    public IEnumerable<SelectListItem> Turnos { get; set; } 
 }

The AddEntity property (which is a StudentModel) would be my LITTLE that will then be mapped with Automapper to your domain class for persistence.

I show how is my AddEntity:

public class AlumnoModel
{
    [Display(Name ="Nombre")]
    public string Nombre { get; set; }

    [Display(Name = "Apellido")]
    public string Apellido { get; set; }

    [Display(Name = "N° Legajo")]
    public string Legajo { get; set; }

    [Display(Name = "Dni")]
    public int Dni { get; set; }

    [Display(Name = "Carrera")]
    public CarreraModel Carrera { get; set; }

    [Display(Name = "Turno")]
    public TurnoModel Turno { get; set; }
}

Almost all the properties of this class are strongly typed except for two, which will be Carrera and Turn which are in turn two other POCOs. I show one because they are identical:

public class TurnoModel
{
    public int TurnoId { get; set; }

    [Display(Name = "Turno")]
    public string Descripcion { get; set; }
}

Then the idea is the following: My AddEntity represents a student, that student has several properties, also has a shift and a career, so you can see it is a ratio of 1 an between the table Turns, Race with Students.

Now, the idea is that when wanting to save a Student from the presentation layer to my database my AddEntity passes to the controller with all its data LESS those that are complex objects. The user chooses a turn and a race through a @Html.DropDownListFor step to show this part of the view:

            <div class="form-group">
                @Html.LabelFor(m => m.AddEntity.Turno)
                @Html.DropDownListFor(m => m.Turnos, Model.Turnos, new { @class = "form-control" })
            </div>

            <div class="form-group">
                @Html.LabelFor(m => m.AddEntity.Carrera)
                @Html.DropDownListFor(m => m.Carreras, Model.Carreras, new { @class = "form-control" })
            </div>

As you can see, I'm creating two DropDown with the ViewModel's Races and Turns properties that are two SelectListItem.

What you try to do is, by jQuery, capture the selected value in these two DropDown and pass it to these two properties that pass through two HiddenFor . These are my Hidden:

@Html.HiddenFor(m => m.AddEntity.Carrera.CarreraId)
@Html.HiddenFor(m => m.AddEntity.Turno.TurnoId)

And here the jQuery:

    if (action === "Save")
    {
        var carreraId = parseInt($("#Carreras option:selected").val());
        var turnoId = parseInt($("#Turnos option:selected").val());

        $("#AddEntity_Turno_TurnoId").val(turnoId);
        $("#AddEntity_Carrera_CarreraId").val(carreraId);
    }

The question would be, is there any better way to binde this data without having to go through jQuery to bindearlo? I know it's a theme of the DefaultModelBinder. Would I have to create a Custom?

    
asked by Nickso 01.12.2017 в 04:15
source

1 answer

0

Let me tell you that you are not using / implementing the MVVM pattern. Possibly there is confusion because in ASP.NET MVC uses the name of "ViewModel", but it is not the same as the ViewModel of the MVVM pattern, it is a simple LITTLE class whose sole purpose is to represent the properties of the model that you want to show in the view

If you have a model with several properties, but in the view you only need a few properties, not all, you create a "ViewModel" with the properties of the model that you will need, so you do not go through the whole model.

There is no "binding" as required by the MVVM pattern unless you use javascript and frameworks as Knockout to do the binning with the DOM.

Although Razor can "binde" what they call "ViewModel", it is still the MVC pattern since the controller fills the view and sends it to the browser, but once in the browser, unless you can modify the DOM with JS , there is no way for the view to update those bindings as in MVVM.

If you do not want to use js (jquery), try with Blazor, you have already released a preview and with Blazor you use c # instead of javascript to modify the DOM.

Or use a framework like DotVVM, which implements the MVVM pattern by creating the ViewModels on the server with c # and adds special html marks that the framework then transforms into kockout, so you do not use jquery or javascript.

Since the ViewModel lives on the server, you can load data directly from the database and you would not need to create an API that is used from javascript.

Example using ViewModel with DotVVM:

public class CalculatorViewModel 
{

    public int Number1 { get; set; }

    public int Number2 { get; set; }

    public int Result { get; set; }

    public void Calculate() 
    {
        Result = Number1 + Number2;
    }
}

Example of the view with DotVVM:

@viewModel DotvvmDemo.CalculatorViewModel, Dotvvm

<p>
  Enter the first number: 
  <dot:TextBox Text="{value: Number1}" />
</p>
<p>
  Enter the second number: 
  <dot:TextBox Text="{value: Number2}" />
</p>
<p>
  <dot:Button Text="Calculate" Click="{command: Calculate()}" />
</p>
<p>
  The result is: {{value: Result}}

The framework takes care of everything, and every time a "binded" value changes in the view, it is updated in the viewmodel as well, and vice versa.

Blazor: link

DotVVM: link

    
answered by 02.04.2018 в 06:42