2013-08-29 14 views
6

Ich versuche, ein Bild und ein Stylesheet von einem Benutzersteuerelement zu eingebetteten Ressourcen in der Assembly zu verschieben. Ich habe Reflector verwendet, um zu sehen, dass die Bild- und CSS-Datei in die Assembly eingebettet sind, aber wenn ich versuche, mit der von ClientScript.GetWebResourceUrl() erstellten URL darauf zuzugreifen, wird die Ressource nicht gefunden. Ich bin ratlos.Ich kann nicht auf eingebettete Ressource in asp.net zugreifen

Assembly Standard-Namespace:

TestWebApp 

die Pfade zu den Dateien (wie Buildaction markiert: Eingebettete Ressource) sind

TestWebApp/Resources/CSS/PaymentHistory.css 
TestWebApp/Resources/Images/loading.gif 

Und so sind meine Ressourcen wie folgt registriert:

[assembly: WebResource("TestWebApp.Resources.CSS.PaymentHistory.css", "text/css", PerformSubstitution = true)] 
[assembly: WebResource("TestWebApp.Resources.Images.loading.gif", "image/gif")] 

Benutzerkontrolle (in derselben Baugruppe), die auf die Ressourcen zugreift:

TestWebApp.UserControls.PaymentHistory 

Um zu vereinfachen, versuche ich gerade, das Bild und nicht das Stylesheet zu referenzieren. In meiner Page_Load Benutzersteuerung, stellte ich die ImageUrl einer Bildsteuerung auf die Ressource URL:

image1.ImageUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "TestWebApp.Resources.Images.loading.gif"); 

Zur Laufzeit erscheint alles ohne Fehler zu arbeiten, aber es macht ein gebrochenes Bild. Hier ist die gerenderten Bild Quelle:

<img style="border-width:0px;" src="/WebResource.axd?d=8fC_1tLPjrUCxmFc_Q2MKY0-pHAak-sTWkpLLV3D56H_c08LujXC63ia2PNICE65_i-Q4JqprAigLpbrXG-rIAr6ePO4HHcdQKgdd3szlThv2gizxOJLJsPRNe-b_M6ApTwPsH_5oZAuONTN0cumOTRr1nA1&amp;t=635133745137507721" id="ph1_image1"> 

Wenn ich auf diese URL in meinem Browser navigieren, erhalte ich eine 404 Die Ressource kann nicht gefunden werden. Was mache ich falsch?

EDIT: Es muss etwas Grundlegendes sein, das ich nicht verstehe und/oder ich mache etwas wirklich dummes. Here is a simple VS 2010 example. Ich habe alle erforderlichen Schritte ausgeführt, die ich kenne, um JScript1.js einzubetten und über WebResource.axd darauf zuzugreifen, aber es wird der Fehler angezeigt.

+2

Im Debug überprüfen, dass Assembly.GetExecutingAssembly(). GetManifestResourceNames(); gibt die erwarteten Ressourcennamen zurück. Ziehen Sie außerdem in Betracht, eine Zeichenfolgenkonstante zu verwenden, um sicherzustellen, dass Sie dieselbe Zeichenfolge in Ihrem WebResource-Attribut und in Ihrem GetWebResourceUrl-Befehl verwenden. – Grax

+0

@Grax - Danke, ich weiß das zu schätzen. Mit GetManifestResourceNames() habe ich mehrfach verifiziert, dass die verwendeten Strings eindeutig übereinstimmen und korrekt sind. Ich habe auch versucht, die Ressourcen aus ihren Unterordnern in den Projektstamm zu verschieben. Ich bemerkte, dass ich einen falschen Inhaltstyp "img/gif" hatte, den ich jetzt zu "image/gif" geändert habe, aber zu meiner Überraschung hat es nicht behoben. Ich habe auch bemerkt, dass das Ausgabefenster zwei System.Web.HttpExceptions mit dem Status "Dies ist eine ungültige WebResource-Anfrage" protokolliert. Ich bin mir nicht sicher, warum es zwei ist ... meine Vermutung war Firefox oder "Cassini" automatisch erneut versucht. – xr280xr

+0

@Grax Ich habe die Frage mit einem Beispiel aktualisiert, wenn Sie es ausprobieren möchten – xr280xr

Antwort

9

In der Default.aspx.cs Datei Ihres Beispielprojekt ändern this.GetType() zu typeof(_Default):

Page.ClientScript.RegisterClientScriptInclude("JScript1", 
    Page.ClientScript.GetWebResourceUrl(typeof(_Default), "EmbeddedResources.JScript1.js")); 

Auch in der PaymentHistory.ascx.cs Datei ändern this.GetType() zu typeof(PaymentHistory):

image1.ImageUrl = Page.ClientScript.GetWebResourceUrl(
    typeof(PaymentHistory), "TestWebApp.Resources.Images.loading.gif"); 

Erläuterung:GetWebResourceUrl untersucht das Argument type, um festzustellen, welche Assembly die eingebettete Ressource enthält. Die Angabe this.GetType() als type ist falsch, da this.GetType() in einer ASPX- oder ASCX-CodeBehind-Klasse nicht auf diese Klasse bezieht, sondern auf die abgeleitete Klasse, die dynamisch aus dem ASPX- oder ASCX-Markup generiert wird.Diese abgeleitete Klasse befindet sich in einer separaten Assembly, sodass GetWebResourceUrl die eingebettete Ressource nicht finden kann.

+0

Wow, ich kann nicht glauben, dass ich nicht daran gedacht habe, dies zu überprüfen.GetType() zur Fehlerbehebung. Ich wusste jedoch nie, dass eine Klasse für vorkompilierte Seiten und Steuerelemente generiert wurde. Vielen Dank, Michael! – xr280xr

+0

@ Xr280xr: Gern geschehen. :-) –

1

Ist die Ressource in einem separaten Projekt oder im selben Projekt wie das Benutzersteuerelement? Wenn Sie separat sind, müssen Sie this.GetType() durch die GetType() - Funktion eines Objekts ersetzen, die sich im separaten Projekt befindet.

Wenn im selben Projekt, nur Page.GetType tun(), weil Sie einen Verweis auf die Seite wollen und nicht die Benutzersteuerung

+0

Ihre Frage wird in meinem OP beantwortet, aber danke, dass Sie auf dieses Detail hingewiesen haben. Die Verwendung von Page.GetType() behebt es nicht.Die Methode, die benötigt wird, ist ein Typ in der Assembly, der die Ressource enthält. In meinem Fall erfüllen sowohl die Seite als auch die Benutzerkontrolle diese Kriterien, so dass es keinen Unterschied geben sollte. – xr280xr

1

Zunächst ist der Typ, den Sie an den GetWebResourceUrl-Aufruf (oder an die RegisterClientScriptResource, die ich unten zeige) übergeben, tatsächlich, um zu zeigen, welche Assembly Ihre Ressource enthält. Das Problem ist, dass "this.GetType()" einen Typ zurückgibt, der nicht in der aktuellen ausführenden Assembly enthalten ist (so seltsam das auch sein mag).

Die folgenden 2 Zeilen veranschaulichen das Problem.

 Response.Write(this.GetType().Assembly.FullName + "<br>"); 
     Response.Write(Assembly.GetExecutingAssembly().FullName + "<br>"); 

Die erste Zeile gibt den Namen eines "App_Web _ ??????" Versammlung. Die zweite gibt die erwartete "EmbeddedResources" -Assembly zurück.

In den folgenden Aufruf gebe ich nur den ersten Typ, den ich von der ausführenden Assembly zurück und der Aufruf funktioniert. Page.ClientScript.RegisterClientScriptResource (Assembly.GetExecutingAssembly(). GetTypes() [0], Namen [0]);

this.GetType() gibt tatsächlich einen Typ zurück, den der Webserver erstellt und der von Ihrem Typ erbt. Deshalb würde typeof (_Default) auch funktionieren, um die korrekte Assembly zu bezeichnen.

+0

Die Verwendung von 'GetTypes() [0]' funktioniert, aber es scheint ein wenig ineffizient, alle Typen in der Assembly zu laden, wenn alles, was Sie brauchen, eins ist. –

0

Hier können Sie einen Code in Vb.NET sehen, der die Reflection-Bibliothek verwendet, um den aktuellen Assembly-Namen und den aktuellen NameSpace zu erkennen.

Wenn Sie den Namespace mit eingebetteten Bildnamen verketten, können Sie den Befehl Page.clientScript.GetWebResourceURL verwenden, um einen Link für Bild zu erzeugen, wie sie in der ersten Funktion siehe

In zweite Funktion finden Sie eine Schleife in allen des Ressourcennamens, bis der vollständige Name der eingebetteten Ressource gefunden wird.

Friend Class ReadResources 

    ' Get our assembly. 
    Private Shared executingAssembly As System.Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly() 

    ' Get our namespace. 
    Private Shared myNamespace As String = executingAssembly.GetName().Name.ToString() 

    ''' <summary> 
    ''' Generate resource link 
    ''' </summary> 
    Friend Shared Function GetResourceLink(ByVal ref As String, 
              ByVal obj As Object, 
              ByVal page As Web.UI.Page) As String 
     Dim out As String = Nothing 
     out = Page.ClientScript.GetWebResourceUrl(obj.GetType, myNamespace & "." & ref) 

     If out Is Nothing OrElse out.Length <= 0 Then 
      out = FindResource(ref, obj) 
     End If 

     Return out 
    End Function 

    Friend Shared Function FindResource(ByVal reference As String, 
             ByVal obj As Object) As String 
     Dim out As String = "" 
     For Each embedded In obj.GetType().Assembly.GetManifestResourceNames() 
      If embedded.Contains(reference) Then 
       out = embedded 
       Exit For 
      End If 
     Next 
     Return out 
    End Function 


End Class 
+0

Bitte vermeiden Sie Code-Only-Antworten. Erwägen Sie, Ihrem Code – MickyD

+0

gemäß Ihrer Empfehlung eine Erklärung hinzuzufügen –