2012-05-04 23 views
6

Ho un'applicazione MVC che sto utilizzando vari endpoint JsonResult per popolare il ViewModel javascript.MVC passa JSON ViewModel a View

Ho utilizzato diverse richieste Ajax jQuery per popolare il modello, ma mi piacerebbe che il modello inital sia passato alla vista sul server.

Il ViewModel ha 3-5 pezzi (a seconda di dove l'utente si trova nell'applicazione):

  1. link della pagina di base, questi non cambiano molto spesso e potrebbe essere la stessa identica per tutta la dell'Utente sessione
  2. Notifiche utente.
  3. Dati utente.
  4. (opzionale) i dati visualizzabili
  5. dati
  6. (opzionale) misc

Attualmente sto usando questo codice per caricare i primi tre pezzi:

$(document).ready(function() { 

    ko.applyBindings(viewModel); 
    @Html.Raw(ViewBag.Script) 

    // Piece 1. Almost always the same thing 
    postJSON('@Url.Action("HomeViewModelJson", "Home")', function (data) { 

     if (data == null) 
      return; 

     for (var i in data.Tabs) { 
      viewModel.tabs.push({ name: data.Tabs[i] }); 
     } 

     for (var i in data.Buttons) { 
      viewModel.metroButtons.push({ name: data.MetroButtons[i] }); 
     } 

     for (var i in data.Ribbons) { 
      viewModel.ribbons.push(data.Ribbons[i]); 
     } 
     ApplyButtonThemes(); 
    }); 
}); 


// Piece 2. Changes constantly. OK as is 
postJSON('@Url.Action("GetNotifications", "NotificationAsync")', function (nots) { 
    viewModel.notifications.removeAll(); 

    ko.utils.arrayForEach(nots, function (item) { 
     item.readNotification = function() { 
      hub.markNotificationAsRead(this.Id); 
      return true; 
     }; 
     viewModel.notifications.push(item); 
    }); 
}); 

// Piece 3. Changes but should also be loaded at startup 
postJSON('@Url.Action("GetUser", "UserAsync")', function (user) { 
    viewModel.user(koifyObject(user)); 
}); 


postJSON = function(url, data, callback) { 
    if($.isFunction(data)) { 
     callback = data; 
     data = {}; 
    } 
    $.ajax({ 
     'type': 'POST', 
     'url': url, 
     'contentType': 'application/json', 
     'data': ko.toJSON(data), 
     'dataType': 'json', 
     'success': callback 
    }); 
}; 

Ho provato a fare qualcosa di simile, ma sto trovando che usando il @Html.Action("HomeViewModelJson", "Home") sta facendo cambiare le intestazioni HTTP e l'intera pagina viene inviata come se fosse JSON

 (function (data) { 

      if (data == null) 
       return; 

      for (var i in data.Tabs) { 
       viewModel.tabs.push({ name: data.Tabs[i] }); 
      } 

      for (var i in data.MetroButtons) { 
       viewModel.metroButtons.push({ name: data.MetroButtons[i] }); 
      } 

      for (var i in data.Ribbons) { 
       viewModel.ribbons.push(data.Ribbons[i]); 
      } 
      ApplyMetroButtonThemes(); 
     })('@Html.Action("HomeViewModelJson", "Home")'); 

Quello che mi piacerebbe fare è utilizzare gli endpoint JsonResult esistenti per ottenere dati Json nel ViewModel sul lato server, prima che la pagina venga inviata all'utente.

Ci sono delle opzioni che mi consentiranno di farlo senza riscrivere i miei controller?

risposta

9

Durante il rendering della vista principale si utilizza un modello di visualizzazione, giusto? In questo modello vista semplicemente popolare le proprietà che non si desidera essere prelevati con AJAX prima di tornare la vista:

public ActionResult Index() 
{ 
    MyViewModel model = ... 
    model.Prop1 = ... 
    model.Prop2 = ... 
    return View(model); 
} 

per esempio se si dispone l'azione seguente che viene utilizzato per le richieste AJAX:

public JsonResult GetProp1() 
{ 
    Property1ViewModel model = ... 
    return Json(model, JsonRequestBehavior.AllowGet); 
} 

si potrebbe utilizzare dall'azione principale per popolare singole proprietà:

model.Prop1 = (Property1ViewModel)GetProp1().Data; 
model.Prop2 = (Property2ViewModel)GetProp2().Data; 

e poi dentro la vista corrispondente si potrebbe usare la Json.Encode metodo per serializzare l'intero modello in una stringa JSON:

@model MyViewModel 
<script type="text/javascript"> 
    var model = @Html.Raw(Json.Encode(Model)); 
    // You could use model.Prop1 and model.Prop2 here 
</script> 

oppure si potrebbe anche serializzare proprietà individuali, se non hai bisogno di tutti loro:

@model MyViewModel 
<script type="text/javascript"> 
    var prop1 = @Html.Raw(Json.Encode(Model.Prop1)); 
</script> 
+0

Che suona come potrebbe funzionare! Fammi provare :) Non sapevo nemmeno che fosse possibile! –

+0

Hai dimenticato di accettare. Ha funzionato alla grande! –

+0

+1 Nizza ............. – SleepyBoBos