2013-10-08 12 views
19

Dato il metodo di estensione seguente stringaPerché il metodo di estensione non è stato trovato in MVC4 Razor View?

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

Un @using stato aggiunto alla visualizzazione MVC4 Razor

@using JHS.ExtensionMethods; 

e il seguente valore di stringa chiama il metodo di estensione

@Model.producer.phone.ToUSAPhone() 

che restituisce il seguente errore

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

Ho anche provato a inserire lo spazio dei nomi nel web.config della cartella/Views e ricevere lo stesso errore.

<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> 

Ho verificato il metodo di estensione funziona mettendo la stessa chiamata in una classe C#

string test=producer.phone.ToUSAPhone(); 

Sembra che il riferimento al metodo di estensione non è disponibile nella vista MVC4 Razor ma posso' t capire perché?

+0

Potrebbe mostrare qualche altro codice della vista? Potresti avere alcuni errori di sintassi. Sei anche sicuro che 'phone' sia di tipo' stringa' e non 'nullo'? –

+1

Nota a margine: l'analisi di un numero, che è * per definizione * intero, in un 'doppio 'è solo * insane * ... –

+1

Seconda nota: il punto e virgola non è necessario dopo il clausole' @ using'. –

risposta

30

Ciò accade se il tipo che si sta tentando di utilizzare il metodo di estensione è in realtà un dynamic. Verificare se l'eccezione viene generata da CSharp RuntimeBinder. Se è così, è possibile utilizzare il metodo come un comune o giardino metodo statico:

@StringExtensions.ToUSAPhone(Model.producer.phone) 

Oppure si può lanciare il valore in una stringa:

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

According to Eric Lippert (ex di MSFT):

Il motivo alla base del fatto che le dinamiche non supportano i tipi di estensione è dovuto al fatto che i metodi di estensione del codice normale e non dinamico funzionano con eseguendo una ricerca completa di tutti Classi note al compilatore per una classe statica con un metodo di estensione corrispondente. La ricerca diventa in base all'annidamento nello spazio dei nomi e alle direttive "utilizzabili" in ogni spazio dei nomi.

Ciò significa che, al fine di ottenere una chiamata di metodo di estensione dinamica risolto correttamente, in qualche modo il DLR deve sapere in fase di esecuzione quello che tutte le nesting namespace e "utilizzando" le direttive erano nel codice sorgente . Non esiste un meccanismo a portata di mano per codificare tutte le informazioni nel sito di chiamata.

+0

L'errore OP citato è: ''string' non contiene una definizione per 'ToUSAPhone''. Il rasoio sa già che è una stringa. – haim770

+0

In realtà, Razor non sa nulla dei tipi di dati. È un linguaggio di template, non un compilatore. Se il tipo è dinamico, come ho detto nella mia risposta, non è una stringa. Il messaggio di errore che l'OP segnala viene generato da RuntimeBinder. Vedi la spiegazione di Eric Lippert su cosa sta succedendo qui: http://stackoverflow.com/questions/5311465/extension-method-and-dynamic-object-in-c-sharp –

+0

Ho pensato che fosse un errore in fase di compilazione. – haim770

0

genera il progetto prima di aggiungere lo spazio dei nomi personalizzati per le estensioni alla vista.

1

Non è solo se il tipo su cui si sta chiamando il metodo di estensione è dinamico, ma se qualcosa nell'espressione è dinamico e non viene eseguito il cast.

ad esempio questo è chiaramente dinamica:

@ViewBag.ToJSON() 

Ma prima ho pensato che la risposta di Mike non si applica a me perché stavo facendo questo:

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

dove ToJSON() è il mio metodo di estensione e GetJSONProfile() solo restituisce object.

Stavo solo distanziando ed essendo stupido ma volevo menzionarlo.

Problemi correlati