web-dev-qa-db-fra.com

Dans ASP.NET MVC / RAZOR, comment ajouter l'initialiseur JavaScript à un "contrôle"?

En fait, j'ai déjà au moins 3 solutions différentes pour le problème, je n'aime tout simplement aucun d'entre eux pour diverses raisons.

Dans ASP.NET MVC/RAZOR, il n'y a plus de commandes, dans le sens qu'elles étaient dans ASP.NET. Un contrôle ASCX utilisée pour afficher + contrôleur entrelacé, donc je l'obtiens. Au lieu de cela, nous avons des aides HTML qui émettent des chaînes, des fragments HTML. Disons que je souhaite créer une méthode d'assistance dans une bibliothèque qui crée un sélecteur de date d'UI jQuery.

Première solution. Je viens d'écrire une méthode qui crée d'abord une zone de texte (en fait, je peux simplement appeler TextBoxFor parce que cela fait la même chose pour moi), il crée un petit fragment de code JavaScript qui appelle $('#textboxid').datepicker(). Ensuite, je peux appeler cela dans mes vues de rasoir et ça marche. Je n'aime pas le fait que des choses liées à la vue sont effectuées dans le code et non dans Razor, mais tous les modèles de rédaction par défaut sont comme ça, malheureusement. Je n'aime pas le fait qu'il y aura beaucoup de petits fragments de script après chaque zone de texte dans la sortie HTML. Et mon fragment de code peut être complexe, si cet initialisateur JS avait de nombreux paramètres, il semblerait moche, il y aurait des problèmes d'échappement à chaînes, etc.

Microsoft pousse l'architecture JavaScript insensible. Je pourrais simplement mettre une classe de marqueur CSS sur ma zone de texte, ajouter des attributs de données si nécessaire, et émettez un seul JavaScript qui transforme toutes mes boîtes de texte sur les ramasseurs de la date, en fonction de la classe de marqueur CSS. Cette dernière partie est le problème principal, j'ai besoin d'un code JS impératif pour faire cela. Discrettrice AJAX et votre validation fonctionne bien parce qu'elles n'en ont pas besoin du tout, ils répondent simplement aux événements d'interaction utilisateur. Ce n'est pas le cas, je dois transformer mes boîtes à mémoire de texte à ce jour. apparaissent. Et ils peuvent apparaître dynamiquement dans une grille modifiable ou après un AJAX appel, chaque fois.

Troisième solution, la vue devrait être effectuée à Razor, alors faites-le dans Razor, comme modèle d'éditeur. Le problème est que nous parlons d'une bibliothèque de classe ici. Dans le passé, j'ai vu des hacks laids pour intégrer des fichiers .cshtml en tant que ressources intégrées ou les compiler au code C # réel pendant la compilation. Enfin, j'ai vérifié, ils semblaient comme des hacks laids et n'étaient pas pris en charge.

Y a-t-il une autre solution? Sinon, lequel de ce qui précède est le plus beau, celui qui se conforme le plus à l'état des conventions de codage de l'art, ou l'idée de Microsoft, etc.?

5
fejesjoco

Je ne suis pas tout à fait sûr que j'ai identifié le bon problème, mais si j'ai, cela peut aider:

Nous avons créé une classe appelée ScriptManager qui nous permet de nous ajouter des fichiers javascript arbitraires et/ou des fonctions au bas de toutes nos pages lorsqu'elles sont rendues. Donnez cela un essai:

public class ScriptManager
{
    public List<string> scripts = new List<string>();
    public List<string> scriptFiles = new List<string>();
}
public static class HtmlExtensions
{

    [ThreadStatic]
    private static ControllerBase pageDataController;
    [ThreadStatic]
    private static ScriptManager pageData;

    public static ScriptManager ScriptManager(this HtmlHelper html)
    {
        ControllerBase controller = html.ViewContext.Controller;

        // This makes sure we get the top-most controller
        while (controller.ControllerContext.IsChildAction)
        {
            controller = controller.ControllerContext.ParentActionViewContext.Controller;
        }
        if (pageDataController == controller)
        {
            // We've been here before
            return pageData;
        }
        else
        {
            // Initial setup
            pageDataController = controller;
            pageData = new ScriptManager();
            return pageData;
        }
    }
}

Ensuite, au bas de votre _Layout.cshtml Page:

@foreach (var script in Html.ScriptManager().scriptFiles.Distinct())
{
    @Html.Script(script);
}
@foreach (var script in Html.ScriptManager().scripts)
{
    @Html.Raw("<script type='text/javascript'>")
    @Html.Raw(script)
    @Html.Raw("</script>")
}

Enfin, vous l'utilisez dans une vue partielle comme:

@{
  Html.ScriptManager().scriptFiles.Add(Url.Content("~/Scripts/jquery.blockUI.js"));
 }

Vous perdez la possibilité de dire au client des scripts dans l'en-tête de la page, mais ils seront inclus dans toutes les pages que vous utilisez une vue partielle qui utilise le blocuii (par exemple).

5
Bobson

Un autre est d'avoir un cshtml et un contrôleur correspondant en dessous. Une telle chose que nous appelons un contrôle et l'intégrer dans une autre vue à l'aide de @Html.RenderPartial('<action_url>', <model>). Dans l'action du contrôleur doit être annotée avec [ChildActionOnly] attribut donc il ne peut pas être appelé dans un appel direct.

Non pas que je suis un grand fan de cette approche, décrivez-le ici donc nous avons une image complète.

Vous pouvez également utiliser le rasoir @helper En plus de vous @Html. aides.

0
SOReader