Question

J'ai une question assez simple pour tous les experts de Razor.J'essaie de faire un appel jQuery $ .ajax () à une URL, en utilisant Url.Content () pour traduire le chemin relatif à la maison en un chemin relatif à la racine.Ce faisant, Razor est un peu confus quant à l'emplacement de la fin de ma @section.Je préférerais pouvoir spécifier l'URL en ligne, mais lorsque je fais cela, Razor pense que la fin de la liste de paramètres $ .ajax () est la fin de ma @section.J'utilise @section parce que je veux utiliser des mises en page pour placer mon javascript au bas de chaque fichier.Pourquoi Razor est-il si confus?J'ai même essayé d'utiliser @ (Url.Content (...)), mais cela ne fonctionne pas non plus.

Est-ce également la meilleure façon d'aborder le problème?J'utilise l'aperçu ASP.NET MVC 4.

Cela fonctionne:

@section Scripts {
    <script type="text/javascript">        
        var getMessagesUrl = '@Url.Content("~/Logging/GetMessages")';

        $(document).ready(function () {
            $.ajax({
                url: getMessagesUrl,
                dataType: 'html',
                success: function (result) {
                    $('tbody').html(result);
                }
            });
        });
    </script>
}

Ce n'est pas le cas:

@section Scripts {
    <script type="text/javascript">        
        $(document).ready(function () {
            $.ajax({
                url: '@Url.Content("~/Logging/GetMessages")',
                dataType: 'html',
                success: function (result) {
                    $('tbody').html(result);
                }
            }); //Razor thinks this is the curly-brace that ends the section!
        });
    </script>
}
Était-ce utile?

La solution 5

Merci pour toute l'aide, mes amis.

Il semble qu'il s'agisse d'un bogue dans l'aperçu d'ASP.NET MVC 4.Je viens de passer à la version bêta d'ASP.NET MVC 4, qui est sortie le 15 février, et le problème a maintenant complètement disparu.

Autres conseils

Ceci est probablement dû au comportement de l'analyseur. Lorsqu'il rencontre le symbole @, l'analyseur passe en mode code et lira l'expression implicite Url.Content("~/Logging.GetMessages") (enfin, en fait, il lira jusqu'à ce que le symbole ', détermine que ce n'est pas un caractère valide dans une expression et trackback pour revenir jusqu'à la fin le ). C'est après cette étape que l'analyseur se confond un peu avec votre vue, car il est probablement en mode code lorsqu'il rencontre le dernier caractère } et pense que c'est la fin d'une étendue de code.

La réalité est que vous devez être très prudent lorsque vous utilisez javascript dans une vue rasoir avec C #. Les transitions vers le code sont explicites, par ex. @ et après un {, mais les transitions vers le balisage sont un peu plus difficiles à déterminer.

Razor mis à part, ma recommandation serait de coller le code de votre application javascript dans un fichier externe et de profiter des attributs data- * pour transmettre des méta-informations au code de votre application, par exemple:

<script id="messageScript" type="text/javascript"
    src="/Scripts/messages.js" 
    data-messages="@Url.Content("~/Logging/GetMessages")"></script>

À laquelle vous pouvez accéder en tant que:

(function($) {

    $(function() {
        var $this = $("#messageScript");
        $.ajax({
            url: $this.attr("data-messages"),
            type: "html",
            success: function(result) {
                $("tbody").html(result);
            }
        });
    });

})(window.jQuery);

Mise à jour: Le symbole "moins que" de Dave ne causait pas le problème, il l'a seulement ajouté dans sa question à des fins d'illustration.

Sur MVC4, j'ai pu isoler le problème.Cela ne compilerait pas:

<script type="text/javascript">
  $(document).ready(function () {
    $.ajax({
      url: '@Url.Content("~/Logging/GetMessages")',
      dataType: 'html',
      success: function (result) {
        $('tbody').html(result);
      }
    }); //<-- test
  });
</script>

Mais ce serait:

<script type="text/javascript">
  $(document).ready(function () {
    $.ajax({
      url: '@Url.Content("~/Logging/GetMessages")',
      dataType: 'html',
      success: function (result) {
        $('tbody').html(result);
      }
    }); //-- test
  });
</script>

On dirait que c'était juste le < dans le commentaire qui l'a lancé.

La réponse de Matthew explique assez bien le comportement (même si, pour être honnête, je ne peux pas reproduire votre problème - ni voir pourquoi cela ne fonctionnerait pas - vos deux exemples fonctionnent très bien ici). Pour une approche différente, vous pouvez dédier une action / vue aux variables javascript générées (urls, paramètres, textes localisés, peu importe), c'est-à-dire:

// Could/should be OutputCached depending on the scenario
public ActionResult Globals()
{
   var model = new ClientGlobalsModel();

   // ClientGlobalsModel has a single (could be more) Dictionary<string, string>
   // (Urls) and a ToJSON() method which uses JavaScriptSerializer to serialize 
   // the object:
   model.Urls.Add("GetMessages", Url.Content("~/Logging/GetMessages"));

   // I mostly use this method for e.g. actions:
   model.Urls.Add("UploadImage", Url.Action("Upload", "Image"));

   Response.ContentType = "text/javascript";

   return View(model);
}

Globals.cshtml:

@model ClientGlobalsModel
@{
    Layout = null; // If you have a layout supplied in e.g. _ViewStart
}
var GLOBALS = @Model.ToJSON()

Oui, cela aurait pu être un simple résultat Content() plutôt qu'une vue - mais lorsque vous avez plus de globaux (par exemple, paramètres + urls + textes), vous voudrez peut-être un contrôle plus facile sur la sortie du script et peut-être sérialiser chaque dictionnaire individuellement. Peut également souhaiter créer un espace de nom pour cette variable "GLOBALS" dans un espace de nom d'application partagé pour éviter de polluer la portée globale.

(par exemple) Index.cshtml:

<script src="@Url.Action("Globals", "Client")"></script>
<script src="@Url.Content("~/Scripts/main.js")"></script>

... qui inclut simplement la sortie de / Client / Globals. Et "main.js", dans lequel nous avons maintenant déplacé le reste de votre script:

main.js (statique):

$(document).ready(function () {
   $.ajax({
      url: GLOBALS.Urls.GetMessages,
      dataType: 'html',
      success: function (result) {
         $('tbody').html(result);
      }
   });
});

Vous pouvez, bien sûr, utiliser le même type d'approche pour afficher quelques paramètres spécifiques à l'utilisateur / au contexte / à la vue directement dans la vue. Pour quelques URL ou données, l'approche data- * attribut peut être meilleure en fonction de vos goûts. Cependant, je ne suis pas fan de l’intégration de tonnes de paramètres fondamentaux dans les attributs de chaque page HTML.

Semble toujours être un problème avec MVC4 / Visual Studio 2010 final, mais voici ma solution:

@section jQueryDocumentReady
{
  @{
  <text>
     // All the javascript and bracers you want here
  </text>
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top