Comment créer une fonction dans un modèle cshtml?

219

J'ai besoin de créer une fonction qui n'est nécessaire que dans un seul fichier cshtml. Vous pouvez considérer ma situation comme des méthodes de page ASP.NET, qui sont des services Web min implémentés dans une page, car ils sont limités à une page. Je connais les assistants HTML (méthodes d'extension), mais ma fonction est juste nécessaire dans un fichier cshtml. Je ne sais pas comment créer une signature de fonction dans une vue. Remarque : j'utilise le moteur de modèle Razor.

Saeed Neamati
la source

Réponses:

279

Vous pouvez utiliser la directive @helper Razor:

@helper WelcomeMessage(string username)
{
    <p>Welcome, @username.</p>
}

Ensuite, vous l'invoquez comme ceci:

@WelcomeMessage("John Smith")
Daniel Liuzzi
la source
13
Vous ne pouvez pas mettre de balises dans les @functionsméthodes, donc j'aime cette réponse.
jfren484
1
Oui, c'est bien mieux que de déclarer une fonction. Beaucoup plus simple.
muglio
2
Mais vous ne pouvez pas retourner de variables (d'où le mot fonction)
Paul
@Paul Je ne comprends pas ce que tu veux dire par là.
Daniel Liuzzi
2
Le noyau asp.net prend-il également en charge @helper?
MuM6oJuM6o
411

pourquoi ne pas simplement déclarer cette fonction dans le fichier cshtml?

@functions{
    public string GetSomeString(){
        return string.Empty;
    }
}

<h2>index</h2>
@GetSomeString()

la source
32
Cela devrait être marqué comme la réponse, car la directive @functions répond spécifiquement aux exigences OP. La fonction Helpers est destinée à une utilisation partagée sur plusieurs fichiers de modèle en plaçant le fichier avec la directive @helper dans un répertoire App_Code. Alors que la directive @functions autorise une fonction à être utilisée uniquement par le modèle qui la déclare.
Jon Davis
7
Notez également que les assistants semblent orientés vers le retour de chaînes comme les autres aides de rasoir le font déjà, et donc la functionssolution offre plus de flexibilité pour les types de retour. Les deux réponses obtiennent +1 dans mon livre, car elles sont toutes les deux des informations utiles.
AaronLS
8
@AaronLS Pour être honnête, les assistants ne renvoient pas de chaînes mais IHtmlString, qui s'occupe de l'encodage HTML pour vous et protège votre application des attaques XSS. Les assistants vous offrent également la commodité de la syntaxe Razor dans l'aide elle-même, que vous perdez avec les fonctions. En d'autres termes, <p>Welcome, @username.</p>contre return new HtmlString("<p>Welcome, " + Html.Encode(username) + ".</p>");.
Daniel Liuzzi
9
cependant, l'utilisation @helperdans une seule vue ne la rend pas disponible pour d'autres vues. la raison pour laquelle j'aime mieux @helper est que vous pouvez mettre du HTML entre vos accolades. @functionsne vous laisse pas (facilement) faire ça.
jfren484
5
Juste pour mémoire: les deux @helperet @functionspeuvent être partagés entre de nombreuses vues, et les deux peuvent être déclarés dans et utilisés par une seule vue (et j'ai personnellement trouvé leur utilisation dans les deux scénarios partagés / simples). À mon humble avis, la seule différence pratique entre eux est le fait qu'un assistant de vue ajoute du sucre syntaxique pour renvoyer des extraits HTML rendus (ou, plus approprié, des HelperResultinstances), tandis qu'une fonction de vue n'est généralement utile que pour renvoyer des types de référence ou de valeur simples.
rsenna
25

Si votre méthode n'a pas à retourner du code HTML et doit faire autre chose, vous pouvez utiliser une méthode lambda au lieu de la méthode d'assistance dans Razor

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

    Func<int,int,int> Sum = (a, b) => a + b;
}

<h2>Index</h2>

@Sum(3,4)
Muhammad Hasan Khan
la source
3
Ça marche, mais c'est loin d'être simple. Mon livre sacré est la simplicité;). Mais merci d'avoir fourni des alternatives.
Saeed Neamati
Il est cependant utile si vous devez accéder aux variables globales de la page dans votre fonction, existe-t-il une autre façon de le faire? : /
Alexandre Daubricourt
1

Si vous souhaitez accéder aux variables globales de votre page, vous pouvez le faire:

@{
    ViewData["Title"] = "Home Page";

    var LoadingButtons = Model.ToDictionary(person => person, person => false);

    string GetLoadingState (string person) => LoadingButtons[person] ? "is-loading" : string.Empty;
}
Alexandre Daubricourt
la source
Depuis C # 7.0, c'est la seule réponse correcte et correcte. GetLoadingState()voici la fonction locale.
Wolfrevo Cats