¿Cómo usar knockout.js con ASP.NET MVC ViewModels?

Generosidad

Ha pasado un tiempo y todavía tengo un par de preguntas pendientes. Espero que agregando una recompensa tal vez estas preguntas serán respondidas.

¿Cómo usar html helpers con knockout.js?

¿Por qué se necesita el documento para que funcione? (Vea la primera edición para obtener más información)

¿Cómo hago algo como esto si estoy usando el mapeo de eliminación directa con mis modelos de vista? Como no tengo una función debido al mapeo.

function AppViewModel() {

    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {

    var currentVal = this.lastName();        // Read the current value

    this.lastName(currentVal.toUpperCase()); // Write back a modified value

};

Quiero usar complementos, por ejemplo, quiero poder revertir los observables como si un usuario cancela una solicitud, quiero poder volver al último valor. De mi investigación, esto parece ser logrado por personas que hacen plugins comoeditables

¿Cómo uso algo así si estoy usando mapeo? Realmente no quiero ir a un método en el que tengo en mi vista la asignación manual donde mapeo cada campo de modo de visualización MVC a un campo de modelo KO, ya que quiero el menor javascript en línea posible y eso parece duplicar el trabajo y eso es Por eso me gusta ese mapeo.

Me preocupa que para hacer este trabajo fácil (mediante el uso del mapeo) pierda mucho poder de KO pero, por otro lado, me preocupa que el mapeo manual solo sea un montón de trabajo y haga que mis puntos de vista contengan demasiada información y podría volverse en el futuro más difícil de mantener (por ejemplo, si elimino una propiedad en el modelo MVC tengo que moverla también en el modelo de visualización de KO)

Mensaje original

Estoy usando asp.net mvc 3 y estoy investigando en el nocaut, ya que se ve muy bien, pero me cuesta mucho entender cómo funciona con asp.net mvc, especialmente los modelos de vista.

Para mi ahora mismo hago algo como esto.

 public class CourseVM
    {
        public int CourseId { get; set; }
        [Required(ErrorMessage = "Course name is required")]
        [StringLength(40, ErrorMessage = "Course name cannot be this long.")]
        public string CourseName{ get; set; }


        public List<StudentVm> StudentViewModels { get; set; }

}

Tendría una Vm que tiene algunas propiedades básicas como CourseName y tendrá una validación simple encima. El modelo Vm puede contener otros modelos de vista también si es necesario.

Luego pasaría este Vm a la Vista donde usaría ayudantes html para ayudarme a mostrarlo al usuario.

@Html.TextBoxFor(x => x.CourseName)

Es posible que tenga algunos bucles foreach o algo para obtener los datos de la colección de modelos de Student View.

Luego, cuando enviara el formulario, usaría jquery yserialize array y enviarlo a un método de acción del controlador que lo vincularía de nuevo al modelo de vista.

Con knockout.js, todo es diferente, ya que ahora tienes modelos de visualización y, por todos los ejemplos que he visto, no usan ayudantes html.

¿Cómo usas estas 2 características de MVC con knockout.js?

encontréeste video y brevemente (los últimos minutos del video @ 18:48) incluye una forma de usar modelos de vista al tener básicamente un script en línea que tiene el modelo de vista knockout.js al que se le asignan los valores en ViewModel.

¿Es esta la única manera de hacerlo? ¿Qué tal en mi ejemplo con una colección de modelos de vista en él? ¿Tengo que tener un bucle foreach o algo para extraer todos los valores y asignarlo en nocaut?

En cuanto a los ayudantes html el video no dice nada sobre ellos.

Estas son las 2 áreas que me confunden muchísimo, ya que no hay mucha gente que parezca hablar de ello y me confunde cómo los valores iniciales y todo llega a la vista cuando el ejemplo es solo un ejemplo de valor codificado.

Editar

Estoy probando lo que Darin Dimitrov ha sugerido y esto parece funcionar (aunque tuve que hacer algunos cambios en su código). No estoy seguro de por qué tenía que usar el documento listo, pero de alguna manera todo no estaba listo sin él.

@model MvcApplication1.Models.Test

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
   <script type="text/javascript">

   $(function()
   {
      var model = @Html.Raw(Json.Encode(Model));


// Activates knockout.js
ko.applyBindings(model);
   });

</script>

</head>
<body>
    <div>
        <p>First name: <strong data-bind="text: FirstName"></strong></p>
        <p>Last name: <strong data-bind="text: LastName"></strong></p>
        @Model.FirstName , @Model.LastName
    </div>
</body>
</html>

Tuve que envolverlo alrededor de un documento de jquery listo para que funcione.

También me sale esta advertencia. No estoy seguro de qué se trata.

Warning 1   Conditional compilation is turned off   -> @Html.Raw

Por lo tanto, tengo un punto de partida que supongo que al menos se actualizará cuando termine de jugar y cómo funciona esto.

Estoy tratando de seguir los tutoriales interactivos, pero en su lugar utilizo un ViewModel.

No estoy seguro de cómo abordar estas partes todavía

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
}

o

function AppViewModel() {
    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    };

Editar 2

He podido resolver el primer problema. No hay idea del segundo problema. Sin embargo, sin embargo. ¿Alguien tiene alguna idea?

 @model MvcApplication1.Models.Test

    @{
        Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
        <title>Index</title>
        <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
       <script type="text/javascript">

       $(function()
       {
        var model = @Html.Raw(Json.Encode(Model));
        var viewModel = ko.mapping.fromJS(model);
        ko.applyBindings(viewModel);

       });

    </script>

    </head>
    <body>
        <div>
            @*grab values from the view model directly*@
            <p>First name: <strong data-bind="text: FirstName"></strong></p>
            <p>Last name: <strong data-bind="text: LastName"></strong></p>

            @*grab values from my second view model that I made*@
            <p>SomeOtherValue <strong data-bind="text: Test2.SomeOtherValue"></strong></p>
            <p>Another <strong data-bind="text: Test2.Another"></strong></p>

            @*allow changes to all the values that should be then sync the above values.*@
            <p>First name: <input data-bind="value: FirstName" /></p>
            <p>Last name: <input data-bind="value: LastName" /></p>
            <p>SomeOtherValue <input data-bind="value: Test2.SomeOtherValue" /></p>
            <p>Another <input data-bind="value: Test2.Another" /></p>

           @* seeing if I can do it with p tags and see if they all update.*@
            <p data-bind="foreach: Test3">
                <strong data-bind="text: Test3Value"></strong> 
            </p>

     @*took my 3rd view model that is in a collection and output all values as a textbox*@       
    <table>
        <thead><tr>
            <th>Test3</th>
        </tr></thead>
          <tbody data-bind="foreach: Test3">
            <tr>
                <td>    
                    <strong data-bind="text: Test3Value"></strong> 
<input type="text" data-bind="value: Test3Value"/>
                </td>
            </tr>    
        </tbody>
    </table>

Controlador

  public ActionResult Index()
    {
              Test2 test2 = new Test2
        {
            Another = "test",
            SomeOtherValue = "test2"
        };

        Test vm = new Test
        {
            FirstName = "Bob",
            LastName = "N/A",
             Test2 = test2,

        };
        for (int i = 0; i < 10; i++)
        {
            Test3 test3 = new Test3
            {
                Test3Value = i.ToString()
            };

             vm.Test3.Add(test3);
        }

        return View(vm);
    }

Respuestas a la pregunta(3)

Su respuesta a la pregunta