Pregunta

Tengo una pregunta bastante simple para todos los expertos en afeitar. Estoy tratando de hacer una llamada jQuery $ .AJAX () a una URL, usando url.content () para traducir la ruta relativa al hogar a una ruta relativa a la raíz. Al hacerlo, Razor se está confundiendo un poco sobre dónde se encuentra el final de mi @section. Prefiero poder especificar la URL en línea, pero cuando hago eso, Razor piensa que el final de la lista de parámetros $ .Jajax () es el final de mi @section. Estoy usando @section porque quiero usar diseños para colocar mi JavaScript en la parte inferior de cada archivo. ¿Por qué Razor se confunde tanto? Incluso he intentado usar @(url.content (...)), pero eso tampoco funciona.

Además, ¿es esta la mejor manera de abordar el problema? Estoy usando la vista previa ASP.NET MVC 4.

Esto funciona:

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

Esto no:

@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>
}
¿Fue útil?

Solución 5

Gracias por toda la ayuda, amigos.

Parece que debe haber sido un error en la vista previa ASP.NET MVC 4. Acabo de actualizar a la Beta ASP.NET MVC 4 que salió el 15 de febrero, y el problema ahora ha desaparecido por completo.

Otros consejos

Esto probablemente se deba al comportamiento del analizador. Cuando se encuentra con el @ símbolo, el analizador cambia al modo de código y leerá la expresión implícita Url.Content("~/Logging.GetMessages") (bueno, en realidad se leerá hasta el ' símbolo, determine que no es un carácter válido en una expresión y un seguimiento para devolver hasta el final del ). Es después de esta etapa que el analizador se está confundiendo un poco con su punto de vista porque es probable que esté en modo de código cuando se encuentra con la final } personaje, y piensa que es el final de un tramo de código.

La realidad es que debes tener mucho cuidado al usar JavaScript dentro de una vista de afeitar con C#. Las transiciones al código son explícitas, por ejemplo @ y después de un {, pero las transiciones a la reducción son un poco más difíciles de determinar.

Dejando a un lado la navaja, mi recomendación sería pegar su código de aplicación JavaScript en un archivo externo y aprovechar los atributos de datos:* para transmitir meta información a su código de aplicación, por ejemplo:

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

A la que puedes acceder como:

(function($) {

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

})(window.jQuery);

Actualizar: El símbolo menos que el símbolo de Dave no estaba causando el problema, solo lo agregó en su pregunta con fines ilustrativos.

En MVC4 pude aislar el problema. Esto no compilaría:

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

Pero esto lo haría:

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

Parece que fue solo el < En el comentario que lo estaba lanzando.

La respuesta de Matthew explica el comportamiento (aunque, para ser sincero, no puedo reproducir su problema, ni veo por qué no funcionaría, ambos ejemplos funcionan bien aquí). Para un enfoque diferente, puede dedicar una acción/vista a las variables de JavaScript generadas (URL, configuración, textos localizados, lo que sea), es decir:

// 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()

Sí, esto podría haber sido un simple Content() Resultado en lugar de una vista, pero cuando tiene más globales (por ejemplo, configuración + URL + textos), es posible que desee un control más fácil sobre la salida del script y tal vez sea serializar cada diccionario individualmente. También puede querer el espacio de nombres de esa variable "Globals" en algún espacio de nombres de aplicaciones compartidas para evitar contaminar el alcance global.

(por ejemplo) index.cshtml:

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

... que simplemente incluye la salida de /cliente /globals. Y "main.js", en el que ahora hemos movido el resto de su guión:

main.js (estático):

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

Por supuesto, puede usar el mismo tipo de enfoque para generar algunas configuraciones específicas de usuario/contexto/vista directamente en la vista. Para algunas URL o datos, el enfoque de atributos de datos:* puede ser mejor dependiendo de sus gustos. No soy fanático del relleno montones Sin embargo, de lo que es básicamente la configuración en atributos en cada página HTML.

Parece ser un problema con MVC4 / Visual Studio 2010 final, pero aquí está mi solución:

@section jQueryDocumentReady
{
  @{
  <text>
     // All the javascript and bracers you want here
  </text>
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top