2011-12-27 1 views
11

Ho bisogno di scrivere il contenuto di un file js da una posizione guidata dalla convenzione (come ~/ClientApp/Controllers/Home/Home.js se si carica la vista situata in ~/Views/Home/Home.cshtml). Come faccio a fare questo?Come intercettare il rendering della vista per aggiungere HTML/JS su tutte le viste parziali?

Esempio: se il file ~/Vista/Home/Home.cshtml assomiglia:

<div id="some-partial-view"> 
    <!-- ... --> 
</div> 

e il file ~/ClientApp/Controller/Home/Home.Controller.js sembra

function HomeController() { 
    //some code 
} 

Poi la vista renderizzata restituito dal server web dovrebbe essere simile (se si utilizza violinista)

<!--ommitted <html> <body> tags --> 

<div id="some-partial-view"> 
    <!-- ... --> 
</div> 

<script type="text/javascript"> 
    function HomeController() { 
     //some code 
    } 
</script> 

Un modo è quello di aggiungere un Helper HTML che lo farà come:

<div id="some-partial-view" ng:Controller="HomeController"> 
    <!-- ... --> 
</div> 
@Html.IncludeController("HomeController") 

Tuttavia, non voglio ripeterlo in tutte le viste parziali.

Qualche idea?

+0

nella vista parziale riferimento il file javascript,

+0

Voglio saltare questo passaggio, quindi la domanda . Vuoi tessere il file js durante il rendering della vista. Anche voler ridurre i viaggi di andata e ritorno, quindi questa non è un'opzione. – leypascua

+0

Non è chiaro cosa intendi per "tessere il file js durante il rendering della vista"? –

risposta

15

si potrebbe scrivere una visualizzazione personalizzata:

public class MyRazorView : RazorView 
{ 
    public MyRazorView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable<string> viewStartFileExtensions, IViewPageActivator viewPageActivator) 
     : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions, viewPageActivator) 
    { 

    } 

    protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance) 
    { 
     base.RenderView(viewContext, writer, instance); 

     var view = (BuildManagerCompiledView)viewContext.View; 
     var context = viewContext.HttpContext; 
     var path = context.Server.MapPath(view.ViewPath); 
     var viewName = Path.GetFileNameWithoutExtension(path); 
     var controller = viewContext.RouteData.GetRequiredString("controller"); 
     var js = context.Server.MapPath(
      string.Format(
       "~/ClientApp/Controllers/{0}/{0}.{1}.js", 
       viewName, 
       controller 
      ) 
     ); 
     if (File.Exists(js)) 
     { 
      writer.WriteLine(
       string.Format(
        "<script type=\"text/javascript\">{0}</script>", 
        File.ReadAllText(js) 
       ) 
      ); 
     } 
    } 
} 

e un motore di visualizzazione personalizzata che restituirà questo punto di vista personalizzato quando una vista parziale deve essere richiesto:

public class MyRazorViewEngine : RazorViewEngine 
{ 
    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) 
    { 
     return new MyRazorView(
      controllerContext, 
      partialPath, 
      null, 
      false, 
      base.FileExtensions, 
      base.ViewPageActivator 
     ); 
    } 
} 

che sarebbe registrato in Application_Start:

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 

    RegisterGlobalFilters(GlobalFilters.Filters); 
    RegisterRoutes(RouteTable.Routes); 

    ViewEngines.Engines.Clear(); 
    ViewEngines.Engines.Add(new MyRazorViewEngine()); 
} 

Probabilmente potrebbe essere necessario modificare alcuni dei percorsi in quanto non era del tutto chiaro nella tua domanda, dove dovrebbero i js essere posizionati esattamente, ma normalmente dovrebbe avere abbastanza dettagli nella risposta.

+0

esattamente quello che stavo cercando :) Pensavo ci fosse un altro modo di scrivere un motore di visualizzazione personalizzato. Grazie mille :) – leypascua

+0

@leypascua, ci sono altri modi, ma questo è il più secco. –

+0

@DarinDimitrov c'è un modo per sostituire tutto l'HTML dallo scrittore con qualcos'altro? Inoltre, come potrei eseguirlo solo quando è la vista usata dall'azione del controller, ad esempio ho un 'HomeController' e un'azione' Home' e voglio che questo codice venga eseguito solo nella vista 'Home'. Oggi è in esecuzione da tutte le visualizzazioni utilizzate nella pagina. – Terkhos

0

che avrebbe più senso per includere tutto ciò che javascript sul ring outter, quindi includere che tramite index.php o dovunque ...

Personalmente io uso jQuery e includono ogni oggetto in questo modo ...

//View Objects 
(function($){ 

var views = { 

    init: function() 
    { 
     this.view1(); 
     this.view2(); 
    }, 
    view1 : function() 
    { 
    // I am 
    }, 
    view2 : function() 
    { 
    // all yours 
    } 

} 
//call/invoke my view objects 
$(function(){ 

    //call view object via init() 
    view.init(); 
}); 

})(jQuery); 
+0

Non un'opzione. L'obiettivo è caricare JS on-demand, solo quando è veramente necessario. – leypascua

+0

if (getElementbyID (id)) {// load me ie: elements.sexyID(); } – Philip