Sono sicuro che ci sono molti modi per farlo. Rendo manualmente la vista dal controller e quindi restituisco la vista renderizzata come parte della mia risposta JSON.
Ciò preserva le responsabilità di ogni entità. Le viste si trovano ancora utilizzando il motore di visualizzazione e possono essere riutilizzate. Il controller conosce poco o nulla sulla vista oltre il suo nome e tipo di modello.
Manuale di rendering
public static class RenderHelper
{
public static string PartialView(Controller controller, string viewName, object model)
{
controller.ViewData.Model = model;
using(var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
return sw.ToString();
}
}
}
Nel vostro metodo di azione:
object model = null; // whatever you want
var obj = new {
someOtherProperty = "hello",
view = RenderHelper.PartialView(this, "_PartialName", model)
};
return Json(obj);
Si noti che sto tornando un tipo anonimo. È possibile restituire qualsiasi tipo (serializzabile) desiderato, purché abbia una proprietà stringa per la vista sottoposta a rendering.
Testing
Test un'azione che utilizza il rendering manuale richiede una leggera modifica. Ciò è dovuto al rendering della vista un po 'prima rispetto al rendering nella pipeline MVC.
Manuale di rendering
- Enter metodo di azione
- Render vista esplicitamente < - questo renderà difficile per testare l'azione di chiamata
- Exit metodo di azione
automatica Rendering
- Enter metodo di azione
- creare un risultato vista
- Exit metodo di azione
- risultato pagina processo (rendendo così la vista)
In altre parole, il nostro processo di rendering manuale prende il via un varietà di altre operazioni che rendono difficile il test (come l'interazione con il gestore di build per compilare la vista).
Supponendo di voler testare il metodo di azione e non il contenuto effettivo della vista, è possibile verificare se il codice è in esecuzione o meno in un ambiente ospitato.
public static string PartialView(Controller controller, string viewName, object model)
{
// returns false from a VS 2013 unit test, true from IIS
if(!HostingEnvironment.IsHosted)
{
// return whatever you want here
return string.Empty;
}
// continue as usual
}
controllando HostingEnvironment.IsHosted
è poco costoso (sotto il cofano, è semplicemente un controllo nullo).
+1 Non ho mai pensato a una classe di aiuto. Questa potrebbe essere la soluzione più elegante. Lo proverò. Grazie. – nthpixel
Non vorresti fare: 'var obj = new {view = RenderHelper.PartialView (this," _PartialName ", viewModel), model = koViewModel};'? O è questo che 'foo' è? O mi sta sfuggendo qualcosa? – nwayve
@Dennis - sì, "foo" rappresenta qualsiasi altro dato che è necessario restituire. Non sono sicuro di quale Knockout abbia bisogno sul client, ma la vista ha bisogno anche di un modello (anche se è nullo). –