Domanda

Sto cercando di creare un'applicazione web in cui voglio essere in grado di collegare assiemi separati.Sto utilizzando l'anteprima 4 di MVC combinata con Unity per l'inserimento delle dipendenze, che utilizzo per creare i controller dai miei assembly di plug-in.Sto utilizzando WebForms (aspx predefinito) come motore di visualizzazione.

Se voglio utilizzare una vista, sono bloccato su quelle definite nel progetto principale, a causa della compilazione dinamica della parte ASPX.Sto cercando un modo corretto per racchiudere i file ASPX in un assembly diverso, senza dover eseguire l'intera fase di distribuzione.Mi sto perdendo qualcosa di ovvio?Oppure dovrei ricorrere alla creazione delle mie visualizzazioni a livello di codice?


Aggiornamento:Ho cambiato la risposta accettata.Anche se la risposta di Dale è molto approfondita, ho optato per la soluzione con un diverso fornitore di percorsi virtuali.Funziona a meraviglia e credo che richieda solo circa 20 righe di codice in totale.

È stato utile?

Soluzione

Essenzialmente si tratta dello stesso problema riscontrato dalle persone con WebForms e nel tentativo di compilare i propri file ASCX UserControl in una DLL.ho trovato questo http://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspx potrebbe funzionare anche per te.

Altri suggerimenti

Mi ci è voluto troppo tempo per farlo funzionare correttamente dai vari esempi parziali, quindi ecco il codice completo necessario per ottenere visualizzazioni da una cartella Views in una libreria condivisa strutturata come una normale cartella Views ma con tutto impostato per essere creato come incorporato risorse.Utilizzerà il file incorporato solo se il file abituale non esiste.

La prima riga di Application_Start:

HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedViewPathProvider());

Il VirtualPathProvider

   public class EmbeddedVirtualFile : VirtualFile
{
    public EmbeddedVirtualFile(string virtualPath)
        : base(virtualPath)
    {
    }

    internal static string GetResourceName(string virtualPath)
    {
        if (!virtualPath.Contains("/Views/"))
        {
            return null;
        }



        var resourcename = virtualPath
            .Substring(virtualPath.IndexOf("Views/"))
            .Replace("Views/", "OrangeGuava.Common.Views.")
            .Replace("/", ".");

        return resourcename;

    }


    public override Stream Open()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();


        var resourcename = GetResourceName(this.VirtualPath);
        return assembly.GetManifestResourceStream(resourcename);
    }




}

public class EmbeddedViewPathProvider : VirtualPathProvider
{


    private bool ResourceFileExists(string virtualPath)
    {

        Assembly assembly = Assembly.GetExecutingAssembly();


        var resourcename = EmbeddedVirtualFile.GetResourceName(virtualPath);
        var result = resourcename != null && assembly.GetManifestResourceNames().Contains(resourcename);
        return result;
    }

    public override bool FileExists(string virtualPath)
    {
        return base.FileExists(virtualPath) || ResourceFileExists(virtualPath);
    }


    public override VirtualFile GetFile(string virtualPath)
    {

        if (!base.FileExists(virtualPath))
        {
            return new EmbeddedVirtualFile(virtualPath);
        }
        else
        {
            return base.GetFile(virtualPath);
        }

    }

}

Il passaggio finale per farlo funzionare è che Web.Config root deve contenere le impostazioni corrette per analizzare le visualizzazioni MVC fortemente tipizzate, poiché quella nella cartella views non verrà utilizzata:

<pages
    validateRequest="false"
    pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
    pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
    userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
  <controls>
    <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
  </controls>
</pages>

Sono necessari un paio di passaggi aggiuntivi per farlo funzionare con Mono.Innanzitutto, devi implementare GetDirectory, poiché tutti i file nella cartella views vengono caricati all'avvio dell'app anziché quando necessario:

public override VirtualDirectory GetDirectory(string virtualDir)
    {
        Log.LogInfo("GetDirectory - " + virtualDir);
        var b = base.GetDirectory(virtualDir);
        return new EmbeddedVirtualDirectory(virtualDir, b);
    }

public class EmbeddedVirtualDirectory : VirtualDirectory
{
    private VirtualDirectory FileDir { get; set; } 

    public EmbeddedVirtualDirectory(string virtualPath, VirtualDirectory filedir)
        : base(virtualPath)
    {
        FileDir = filedir;
    }

    public override System.Collections.IEnumerable Children
    {
        get { return FileDir.Children; }
    }

    public override System.Collections.IEnumerable Directories
    {
        get { return FileDir.Directories; }
    }

    public override System.Collections.IEnumerable Files
    {
        get {

            if (!VirtualPath.Contains("/Views/") || VirtualPath.EndsWith("/Views/"))
            {
                return FileDir.Files;
            }

            var fl = new List<VirtualFile>();

            foreach (VirtualFile f in FileDir.Files)
            {
                fl.Add(f);
            }


            var resourcename = VirtualPath.Substring(VirtualPath.IndexOf("Views/"))
.Replace("Views/", "OrangeGuava.Common.Views.")
.Replace("/", ".");

            Assembly assembly = Assembly.GetExecutingAssembly();

            var rfl = assembly.GetManifestResourceNames()
                .Where(s => s.StartsWith(resourcename))
                .Select(s => VirtualPath + s.Replace(resourcename, ""))
                .Select(s => new EmbeddedVirtualFile(s));
            fl.AddRange(rfl);

            return fl;
        }
    }
}

Infine, le visualizzazioni fortemente tipizzate funzioneranno quasi, ma non del tutto, perfettamente.Il modello verrà trattato come un oggetto non digitato, quindi per ottenere una digitazione efficace è necessario avviare le visualizzazioni condivise con qualcosa di simile

<% var Model2 = Model as IEnumerable<AppModel>;  %>
protected void Application_Start()
{
    WebFormViewEngine engine = new WebFormViewEngine();

    engine.ViewLocationFormats = new[] { "~/bin/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" };
    engine.PartialViewLocationFormats = engine.ViewLocationFormats;

    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(engine);

    RegisterRoutes(RouteTable.Routes);
}

Imposta la proprietà "Copia nell'output" della tua vista su "Copia sempre"

Un'aggiunta a tutti voi che state ancora cercando il Santo Graal:Sono arrivato un po' più vicino a trovarlo, se non sei troppo attaccato al motore di visualizzazione dei moduli web.

Recentemente ho provato il motore di visualizzazione Spark.Oltre ad essere assolutamente fantastico e non tornerei ai moduli web anche se fossi minacciato, fornisce anche alcuni ganci molto carini per la modularità di un'applicazione.L'esempio nei loro documenti utilizza Windsor come contenitore IoC, ma non riesco a immaginare che sia molto più difficile se si desidera adottare un altro approccio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top