webentwicklung-frage-antwort-db.com.de

Warum wurde die Erweiterungsmethode in MVC4 Razor View nicht gefunden?

Gegeben die folgende Zeichenkettenerweiterungsmethode

namespace JHS.ExtensionMethods
{
  public static class StringExtensions
  {
    public static string ToUSAPhone(this String str)
    {
      return String.Format("{0:(###) ###-####}", Double.Parse(str));
    }
  }
}

Der MVC4 Razor-Ansicht wurde eine @using-Anweisung hinzugefügt

@using JHS.ExtensionMethods;

und der folgende Zeichenfolgenwert ruft die Erweiterungsmethode auf

@Model.producer.phone.ToUSAPhone()

was zu folgendem Fehler führt

'string' does not contain a definition for 'ToUSAPhone'

Ich habe auch versucht, den Namespace in die Datei "web.config" des Ordners "/ Views" einzufügen, und die gleiche Fehlermeldung erhalten.

<pages pageBaseType="System.Web.Mvc.WebViewPage">
  <namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Optimization"/>
    <add namespace="System.Web.Routing" />
    <add namespace="JHS.ExtensionMethods"/>
  </namespaces>
</pages>

Ich habe überprüft, ob die Erweiterungsmethode funktioniert, indem ich den gleichen Aufruf in eine C # -Klasse gestellt habe

string test=producer.phone.ToUSAPhone();

Es scheint, dass der Verweis auf die Erweiterungsmethode in der MVC4 Razor-Ansicht nicht verfügbar ist, aber ich kann nicht herausfinden, warum?

20
ChrisP

Dies passiert, wenn der Typ, für den Sie die Erweiterungsmethode verwenden möchten, tatsächlich eine dynamic ist. Überprüfen Sie, ob die Ausnahme vom CSharp RuntimeBinder generiert wird. In diesem Fall können Sie die Methode entweder als allgemeine oder als statische Gartenmethode verwenden:

@StringExtensions.ToUSAPhone(Model.producer.phone)

Oder Sie können den Wert in eine Zeichenfolge umwandeln:

@(((string)Model.producer.phone).ToUSAPhone())

Laut Eric Lippert (ehemals von MSFT):

Der Grund für die Tatsache, dass Dynamics keine Erweiterungstypen unterstützt, besteht darin, dass in regulären, nicht dynamischen Codeerweiterungsmethoden alle dem Compiler bekannten Klassen nach einer statischen Klasse durchsucht werden, deren Erweiterungsmethode übereinstimmt. Die Suche erfolgt in der Reihenfolge der Namespace-Verschachtelung und der verfügbaren Using-Direktiven in jedem Namespace.

Das bedeutet, dass das DLR zur Laufzeit irgendwie wissen muss, welche Namensraumverschachtelungen und "using" -Anweisungen sich in Ihrem Quellcode befanden, damit ein dynamischer Erweiterungsmethodenaufruf korrekt aufgelöst wird. Es gibt keinen praktischen Mechanismus, um all diese Informationen in die Anrufstelle zu kodieren.

33
Mike Brind

Es ist nicht nur so, dass der Typ, für den Sie die Erweiterungsmethode aufrufen, dynamisch ist, sondern auch, ob der Ausdruck dynamisch ist und nicht umgewandelt wird.

zB ist dies eindeutig dynamisch:

@ViewBag.ToJSON()

Aber ich dachte zuerst, Mikes Antwort würde nicht auf mich zutreffen, weil ich das tat:

@(ViewBag.UserProfile.GetJSONProfile().ToJSON())

dabei ist ToJSON() meine Erweiterungsmethode und GetJSONProfile() gibt nur object zurück.

Ich habe mich nur abgesetzt und war dumm, wollte das aber erwähnen.

1
Simon_Weaver

Erstellen Sie Ihr Projekt, bevor Sie Ihren benutzerdefinierten Namespace für die Erweiterung zu Ihrer Ansicht hinzufügen.

0

Es mag noch einen anderen trivialen Grund dafür geben, und mir ist es passiert.

Die Datei, in der ich meine Erweiterung erstellt habe, hatte "Content" als Wert für die Eigenschaft "Build Action" im VS-Dateieigenschaftenbereich.

Das Umstellen auf "Kompilieren" hat das Problem natürlich sofort behoben ...

0
Martin