martes, 14 de febrero de 2012
Como sabemos, los helpers como
Por ejemplo, el siguiente código genera un enlace hacia la acción
Esta es una pregunta que suelo ver muy a menudo en comunidades y foros (como el de ASP.NET MVC en MSDN) y me han realizado más de una vez en el curso de ASP.NET MVC 3 que tutorizo en CampusMVP, así que vamos a ver un par de enfoques para enfrentarnos a este escenario, bastante frecuente al trabajar en sistemas web y, sobre todo, en aquellos muy basados en scripting y Ajax.
1. El escenario
Supongamos que tenemos un controlador como el siguiente, cuya única misión es retornar una cadena de texto basándose en los dos parámetros que se le suministran:
Imaginad ahora una vista con un código como el siguiente, en el que creamos un par de controles de edición de texto, un botón de envío y un
La única cuestión entonces es cómo conseguir establecer el valor correcto de la URL de forma sencilla y sin cometer algunos errores muy frecuentes.
Bueno, y si hemos dicho que este código funciona sin problemas, ¿por qué es incorrecto? Pues básicamente porque al construir la URL mediante esta concatenación estamos asumiendo que una petición de tipo
O en otras palabras, al construir la URL de esa forma estamos introduciendo una sutil dependencia hacia el esquema de URLs utilizado por nuestra aplicación y, por tanto, hacia el contenido de la tabla de rutas. De hecho, es bastante fácil que nuestro script deje de funcionar si modificamos la ruta por defecto, por ejemplo como se muestra seguidamente:
Una variación del ejemplo incorrecto anterior es cuando se introduce por medio una llamada al helper
En resumen, podríamos decir que la introducción de direcciones “hardcodeadas” en la vista es un antipatrón que conviene evitar a toda costa utilizando los helpers de generación de URL que nos proporciona el framework, como
Pero claro, el problema es que estos helpers se ejecutan en servidor, y el valor de los parámetros que debemos suministrarles se conocen exclusivamente en cliente… ¿cómo podemos solucionar esto?
Para que lo veáis más claramente, el código real que sería enviado al cliente tras procesarse la vista sería el siguiente, centrándonos en las líneas donde se genera la URL y se reemplazan los valores de los parámetros:
Recordad también que puede ser bastante conveniente codificar con
url = url.replace("param-name", encodeURIComponent(name));
¡Y eso es todo! Ya a partir de implementar esta solución, habremos eliminado la dependencia hacia la tabla de rutas puesto que la URL se generará siempre atendiendo a ella. Sin embargo, es demasiado código para escribir cada vez que nos encontremos con este escenario, ¿no? Veamos varias formas de conseguirlo.
De hecho, lo que vamos a ver es cómo conseguir dejar nuestra función
Partiendo de esta información, el helper será capaz de generar el código script de sustitución de los parámetros en forma de función anónima autoejecutada. El siguiente código muestra el script enviado finalmente al cliente tras procesar la vista anterior:
La idea consiste en crear un helper que reciba un árbol de expresión, cuyos parámetros sean nombrados exactamente igual que las variables de script que deseamos reemplazar en el resultado; el cuerpo de la lambda se ejecutará y se realizarán los reemplazos de forma automática. De esta forma, nuestro método
Y a partir de ahí, el funcionamiento es simple: al método
En primer lugar vimos cómo solucionarlo de forma manual, generando URLs con parámetros ficticios y reemplazándolos a posteriori por los valores reales, y a continuación hemos visto dos posibles enfoques para automatizar esta tarea que espero que os sean de utilidad.
Descargar proyecto de ejemplo (VS2010 + MVC 3)
Publicado en Variable not found.
Url.Action()
y Html.ActionLink()
son capaces de generar URLs hacia acciones partiendo de la información disponible en la tabla de rutas y de los parámetros que les suministramos. Por ejemplo, el siguiente código genera un enlace hacia la acción
Edit
del controlador Friends
, suministrándole el valor 3 al parámetro de ruta id
:@Html.ActionLink("Edit friend", "Edit", "Friends", new {id = 3}, null)
Sin embargo, estos helpers no nos ayudan demasiado cuando desconocemos a priori el valor de los parámetros. De hecho, si en lugar del 3 que hemos suministrado quisiéramos enviar un valor obtenido a través de scripting tendríamos un problema, puesto que el bloque de código anterior se ejecuta en servidor y el enlace sería generado antes incluso de ejecutarse el script para obtener el valor a enviar.Esta es una pregunta que suelo ver muy a menudo en comunidades y foros (como el de ASP.NET MVC en MSDN) y me han realizado más de una vez en el curso de ASP.NET MVC 3 que tutorizo en CampusMVP, así que vamos a ver un par de enfoques para enfrentarnos a este escenario, bastante frecuente al trabajar en sistemas web y, sobre todo, en aquellos muy basados en scripting y Ajax.
1. El escenario
Supongamos que tenemos un controlador como el siguiente, cuya única misión es retornar una cadena de texto basándose en los dos parámetros que se le suministran:
public class InfoController : Controller
{
// GET /info/show/4?name=Joe
public ActionResult Show(string id, string name)
{
return Content(
string.Format("{0}, your ID is {1}", name, id)
);
}
}
Observad el ejemplo de URL mediante la cual podría accederse a esta acción utilizando la ruta por defecto. Volveremos después a ella.Imaginad ahora una vista con un código como el siguiente, en el que creamos un par de controles de edición de texto, un botón de envío y un
<div>
en principio vacío, pero que después utilizaremos para mostrar información obtenida desde el servidor:<fieldset> <legend>Data</legend> <div class="field"> <label for="Id">Your ID:</label> <input type="text" id="Id" /> </div> <div class="field"> <label for="Name">Your name:</label> <input type="text" id="Name" /> </div> <br /> <input type="button" id="send" value="Send" /> </fieldset> <fieldset> <legend>Result</legend> <div id="result"></div> </fieldset>Y ya puestos a echarle imaginación, supongamos ahora que añadimos el siguiente script, que añade al evento
click
del botón algo de lógica:<script type="text/javascript">
$(function() {
$("#send").click(function() {
var id = $("#Id").val();
var name = $("#Name").val();
updateResult(id, name);
return false;
});
});
</script>
Como podéis ver, al pulsar el botón se obtienen los valores de ambos cuadros de texto y se invoca a la función updateResult()
. Ésta se encargará de llamar a la acción del servidor pasándole ambos valores e introduciendo el resultado obtenido en el “hueco” (<div id="result">
) que hemos habilitado para ello; su estructura general será la siguiente: function updateResult(id, name) {
var url = _______ ; // Establecer URL de la acción
$("#result").load(url);
}
El método load() de jQuery efectuará una petición GET a la URL indicada y el contenido retornado por el servidor será introducido en los elementos seleccionados previamente, en este caso el elemento con identificador result
.La única cuestión entonces es cómo conseguir establecer el valor correcto de la URL de forma sencilla y sin cometer algunos errores muy frecuentes.
2. Cómo NO hacerlo bien
La implementación que solemos encontrar con más frecuencia es parecida a la siguiente: // ¡Ojo, no utilizar!
function updateResult(id, name) {
var url = "/info/show/" + id + "?name=" + name;
$("#result").load(url);
}
Este código, que funciona perfectamente, compone la URL concatenando la porción estática de la dirección (“/info/show/
”) con el identificador (el valor de id
) y añade el parámetro name
en la query string con su valor correspondiente.Bueno, y si hemos dicho que este código funciona sin problemas, ¿por qué es incorrecto? Pues básicamente porque al construir la URL mediante esta concatenación estamos asumiendo que una petición de tipo
/info/show/007?name=James
nos llevará hacia la acción que esperamos ejecutar, cuando esto no tiene por qué ser cierto. De hecho, en este caso hemos podido hacerlo así y funciona porque conocemos de antemano la URL de la acción al estar usando la ruta por defecto de los proyectos ASP.NET MVC; si ésta cambia, dejará de funcionar.O en otras palabras, al construir la URL de esa forma estamos introduciendo una sutil dependencia hacia el esquema de URLs utilizado por nuestra aplicación y, por tanto, hacia el contenido de la tabla de rutas. De hecho, es bastante fácil que nuestro script deje de funcionar si modificamos la ruta por defecto, por ejemplo como se muestra seguidamente:
routes.MapRoute(
"Default", // Route name
"{action}/{controller}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Con esta nueva ruta, el acceso a nuestra acción debería ser a través de una URL del tipo /show/info/007?name=James
, por lo que el script anterior dejaría de funcionar de forma silenciosa: no encontraremos ningún error de compilación, ni siquiera en tiempo de ejecución, simplemente no funcionará al estar apuntando hacia una dirección incorrecta.Una variación del ejemplo incorrecto anterior es cuando se introduce por medio una llamada al helper
Url.Action()
para obtener la primera parte de la URL: // ¡Ojo, no utilizar!
function updateResult(id, name) {
var url = "@Url.Action("show", "info")/" + id + "?name=" + name;
$("#result").load(url);
}
Esto, que probablemente hayáis utilizado o visto alguna vez, también es incorrecto. Aunque con un poco de suerte funcionará e incluso será sensible a determinados cambios en la tabla de rutas, seguimos asumiendo que las URL responden a un determinado patrón.En resumen, podríamos decir que la introducción de direcciones “hardcodeadas” en la vista es un antipatrón que conviene evitar a toda costa utilizando los helpers de generación de URL que nos proporciona el framework, como
Url.Action()
o Html.ActionLink()
, donde sí se tiene en cuenta el contenido de la tabla de rutas.Pero claro, el problema es que estos helpers se ejecutan en servidor, y el valor de los parámetros que debemos suministrarles se conocen exclusivamente en cliente… ¿cómo podemos solucionar esto?
3. Primera solución, versión artesana
Esta solución, bastante generalizada, consiste en generar la URL utilizando los helpers que ASP.NET MVC nos ofrece para ello, pero introduciendo “marcadores” en los parámetros que nos permitan reemplazarlos posteriormente por los valores correctos conocidos por el script: function updateResult(id, name) {
var url = "@Url.Action("Show", "Info", new { id="param-id", name="param-name" })";
url = url.replace("param-id", id)
.replace("param-name", name);
$("#result").load(url);
}
Observad que en la variable url
lo que se introducirá será una URL perfectamente generada por el helper Url.Action()
utilizando el sistema de routing, pero el valor de los parámetros id
y name
serán, respectivamente “param-id
” y “param-name
”, que son constantes arbitrarias que estemos completamente seguros de que no van a aparecer en ninguna otra parte de la URL. A continuación, desde el script, reemplazamos esa constante por los valores reales, y listo :-)Para que lo veáis más claramente, el código real que sería enviado al cliente tras procesarse la vista sería el siguiente, centrándonos en las líneas donde se genera la URL y se reemplazan los valores de los parámetros:
...
var url = "/Info/Show/param-id?name=param-name";
url = url.replace("param-id", id)
.replace("param-name", name);
...
Sólo añadir un par de consejos si vais a utilizar este método. Primero, al elegir el valor ficticio para los parámetros, mejor no usar caracteres extraños, puesto que Url.Action()
los codificará para generar la URL y os causará problemas a la hora de reemplazarlo. Lo mejor es seguir un esquema simple, similar al utilizado en el ejemplo, y sobre todo que sean fácilmente identificables para que el código sea claro y legible.Recordad también que puede ser bastante conveniente codificar con
encodeURIComponent()
el valor que vais a reemplazar para que pueda ser introducido de forma segura en una URL, es decir, hacer el replace()
de la siguiente forma:url = url.replace("param-name", encodeURIComponent(name));
¡Y eso es todo! Ya a partir de implementar esta solución, habremos eliminado la dependencia hacia la tabla de rutas puesto que la URL se generará siempre atendiendo a ella. Sin embargo, es demasiado código para escribir cada vez que nos encontremos con este escenario, ¿no? Veamos varias formas de conseguirlo.
4. Segunda solución, automatización con helpers
Si prestamos un poco de atención podemos automatizar la generación de todo el código anterior desde un helper, consiguiendo una solución relativamente integrada y compacta.De hecho, lo que vamos a ver es cómo conseguir dejar nuestra función
updateResult()
en algo tan simple como lo siguiente:function updateResult(id, name) { var url = @Script.Action("show", "info", new { id="js:id", name="js:name"}); $("#result").load(url); }El helper
Script.Action()
, cuyo código veremos algo más adelante, es exactamente igual al conocido Url.Action()
, salvo en que cuando el valor asignado a alguno de sus parámetros de ruta comienza por el prefijo “js:”, su valor es sustituido por la variable de script indicada en él. Así, en el código anterior, al parámetro de ruta id
se asignará el valor de la variable id
del script, y lo mismo ocurrirá con name
.Partiendo de esta información, el helper será capaz de generar el código script de sustitución de los parámetros en forma de función anónima autoejecutada. El siguiente código muestra el script enviado finalmente al cliente tras procesar la vista anterior:
function updateResult(id, nombre) {
var url = (function() {
return '/js%3aid/show/info?name=js%3Anombre'
.replace(/js(%)3[aA]id/, encodeURIComponent(id))
.replace(/js(%)3[aA]nombre/, encodeURIComponent(nombre));
})();
$("#result").load(url);
}
Al final del post encontraréis un enlace hacia el proyecto Visual Studio donde podéis obtenerlo completo y verlo en ejecución, pero os muestro aquí el código, que tampoco es que tenga demasiada chicha:public static partial class Script
{
public static MvcHtmlString Action(string action, string controller, object routeData)
{
var data = new RouteValueDictionary(routeData);
var scriptVarsToReplace = getScriptVars(data);
var requestContext = ((MvcHandler)HttpContext.Current.Handler).RequestContext;
var urlPattern = UrlHelper.GenerateUrl(null, action, controller, data,
RouteTable.Routes, requestContext,
true);
var url = generateFunction(urlPattern, scriptVarsToReplace);
return MvcHtmlString.Create(url);
}
private static IEnumerable<string> getScriptVars(IDictionary<string, object> dictionary)
{
var scriptVariables = new List<string>();
foreach (var prop in dictionary)
{
var value = prop.Value as string;
if (value != null && value.StartsWith("js:") && value.Length > 3)
{
var varName = value.Substring(3);
scriptVariables.Add(varName);
}
}
return scriptVariables;
}
private static string generateFunction(string urlPattern, IEnumerable<string> scriptVars)
{
var sb = new StringBuilder();
sb.Append("(function() {");
sb.AppendFormat(" return '{0}'", urlPattern);
foreach (var variable in scriptVars)
{
sb.AppendFormat(".replace(/{0}/, encodeURIComponent({1}))",
"js(%)3[aA]" + variable,
variable);
}
sb.Append("; })()");
return sb.ToString();
}
}
Por simplificar el ejemplo no he implementado otras sobrecargas de Script.Action()
similares a las que encontramos en Url.Action()
, pero sería ya bastante sencillo partiendo de este código.5. Tercera solución, usando árboles de expresión
Otra posibilidad que se me ocurre es utilizar árboles de expresión para llenar virtualmente el hueco existente entre la ejecución en servidor y la ejecución en cliente creando la ilusión de continuidad. Pero ojo, que no he tenido en cuenta aspectos como el rendimiento, se trata sólo de una prueba de concepto.La idea consiste en crear un helper que reciba un árbol de expresión, cuyos parámetros sean nombrados exactamente igual que las variables de script que deseamos reemplazar en el resultado; el cuerpo de la lambda se ejecutará y se realizarán los reemplazos de forma automática. De esta forma, nuestro método
updateResult()
quedaría algo así:function updateResultExpressionTree(id, name) { var url = @Script.Replace((id, name)=> Url.Action("show", "info", new {id, name})) ; $("#result").load(url); }Como podéis comprobar, este sistema se basa en una asunción algo ingenua pero efectiva: que los nombres de los parámetros que reciba la expresión lambda coincidan con los de las variables de script que queremos suministrarle.
Y a partir de ahí, el funcionamiento es simple: al método
Replace()
le llega un árbol de expresión que una vez compilado es invocado suministrándole como parámetros valores ficticios (generados a partir del nombre del propio parámetro), y es capaz de generar una función de script que realiza el reemplazo de forma automática. El código enviado al cliente tras procesarse la porción anterior será: function updateResultExpressionTree2(id, name) {
var url = (function() {
return '/info/show/param-id?name=param-name'
.replace('param-id', encodeURIComponent(id))
.replace('param-name', encodeURIComponent(name));
})() ;
$("#result").load(url);
}
Y a continuación podéis ver cómo está implementado. Sólo he creado la sobrecarga de Replace()
para árboles de expresión con dos parámetros, pero el resto de versiones serían idénticas (las podéis ver en el proyecto de demostración):public static partial class Script
{
public static MvcHtmlString Replace<TResult>(Expression<Func<string, string, TResult>> expression)
{
return replaceInternal(expression);
}
private static MvcHtmlString replaceInternal(LambdaExpression expression)
{
var parameters = expression.Parameters
.Select(param => paramPlaceHolder(param.Name)).ToArray();
var urlPattern = getResultPattern(expression, parameters);
var sb = new StringBuilder();
sb.Append("(function() {");
sb.AppendFormat(" return '{0}'", urlPattern);
foreach (var parameter in expression.Parameters)
{
sb.AppendFormat(".replace('{0}', encodeURIComponent({1}))",
paramPlaceHolder(parameter.Name), parameter.Name);
}
sb.Append("; })()");
return MvcHtmlString.Create(sb.ToString());
}
private static string paramPlaceHolder(string paramName)
{
return "param-" + paramName;
}
private static string getResultPattern(LambdaExpression expression, params object[] args)
{
var func = expression.Compile();
object result = func.DynamicInvoke(args);
return result.ToString();
}
}
La parte que podría penalizar el rendimiento principalmente es la compilación de la expresión lambda, pero es algo que puede solucionarse rápidamente implementando un caché. Os lo dejo de deberes ;-)6. En resumen…
En este post hemos visto distintas fórmulas para solucionar un problema que encontramos con relativa frecuencia: generar URLs en las que debemos incluir parámetros conocidos únicamente en tiempo de cliente, es decir, desde script.En primer lugar vimos cómo solucionarlo de forma manual, generando URLs con parámetros ficticios y reemplazándolos a posteriori por los valores reales, y a continuación hemos visto dos posibles enfoques para automatizar esta tarea que espero que os sean de utilidad.
Descargar proyecto de ejemplo (VS2010 + MVC 3)
Publicado en Variable not found.
Publicado por José M. Aguilar a las 10:06 a. m.
Etiquetas: asp.net, aspnetmvc, consultas, desarrollo, trucos
25 Comentarios:
Excelente artículo, me ha encantado! Pese a lo extenso que es, engancha desde el principio hasta el final.
Muchas gracias! :-))
Yo cada vez que mezclo código razor con script tengo problemas...
Considera que la última llave de cierre de la función del script pertenece a razor (hasta la pone amarilla) y no hay forma de decirle lo contrario (ni con , ni con @:, ni metiéndolo en llaves...). Tal vez sea por usar la preview de MVC-4
Perdón, ya sé por qué es... Al meter el script en un apartado @Section, Razor confunde el cierre de la sección con el cierre de una función javascript si se mete en ésta algún código Razor adicional. Y esto pasa incluso creando una nueva solución de Visual Studio y copiando tu código ahí. Sin embargo, si abro tu solución directamente, no me pasa... en fin, entiendo que es un off-topic a este tema. Siento el throlling...
@Anónimo, esta es tu casa ;-)
De hecho, ahora iba a responderte diciéndote que no debería ocurrirte nada de eso, pero ya me lo has ahorrado.
Un saludo & gracias por comentar.
Bueno, si no te molestan estos comentarios tan 'laterales' te diré que no está arreglado. Creo que es debido a un bug en MVC4-Preview (o algo en mi Visual Studio). Lo que pasa es que tu fichero de proyecto no hace referencia a MVC-4 (en debe estar E3E379DF-F4C6-4180-9B81-6769533ABE47 en vez de E53F8FEA-EAE0-44A6-8774-FFD645390401, que es de MVC3 - Verás que al añadir una nueva vista te pone el nombre por defecto como ViewPage1 en vez de View1). Tal vez por algo de eso no falla ni aún metiendo el script dentro de una @section (como debe ser). Creando un nuevo proyecto MVC4 colgando de tu solución me falla igualmente. Si creo un MVC3 va todo perfecto... creo que es algo del proyecto.
En fin, gracias por tu respuesta y por toda la ayuda que nos da tu blog.
Muy bueno!!! es lo que estaba necesitando, Gracias
@anónimo, por si te sirve de algo saberlo, a mi no me pasa. Creo un section, en su interior un script, y dentro uso otros bloques Razor, y me funciona todo bien. Misterios del VS, bug de MVC4, o quién sabe...
@ramiro: me alegro de que te sea útil.
Y gracias a ambos por comentar :-)
Bueno, con este post termino mi 'extraño' problema.
He actualizado el MVC4 Developer Preview a MVC4 beta y el problema ha desaparecido. Muchas gracias de nuevo por el soporte!
Genial!!!! Absolutamente brillante!
Me quedo con el mecanismo (4), el (5) creo que no aporta nada especialmente útil y probablemente penalice en rendimiento, no?
La verdad es que yo hasta ahora venía utilizando el (3) pero voy a incorporar este helper a mi batería de helpers!!! :p
;-)
Hola, eduard! :-)
Gracias por tu comentario.
Sí, la solución (4) es la más razonable y simple.
De hecho, la (5) es más una prueba de concepto que otra cosa, pero me pareció curioso el utilizar el dinamismo y flexibilidad del árbol de expresión como puente entre cliente y servidor.
En cuanto al rendimiento, está claro que la compilación del árbol tiene que penalizar, aunque supongo que usando una caché podría mejorarse bastante. Pero ciertamente tampoco tengo pruebas empíricas que lo demuestren ;-)
Muchas gracias de nuevo por comentar!
Buen artículo,
tengo una pregunta, este código funciona si se encuentra dentro de una vista que interpreta el código de servidor.
¿Como resolver esto mismo si la función js se encuentra dentro de un archivo js?
¿Hay forma de ejecutar código de servidor en archivos js? (en las primeras versiones de asp se podía)
Al no encontrar como uso una url en el script apuntado a una acción en un nuevo controlador para generar el contenido dinámicamente.
Muchas gracias. Saludos!
Gracias, unknown :-)
En el momento que se trata de un archivo estático (como un .js), poco puedes hacer desde el servidor, aunque afortunadamente hay varias fórmulas para conseguir el mismo resultado.
Una de ellas es la que comentas, hacer que la referencia desde la vista a tu script apunte a una acción que sea la que lo genera en servidor. Conceptualmente, es correcta.
Otra posibilidad sería aislar tu script genérico en un .js, pero que los métodos u objetos que vayas a utilizar reciban parámetros, que serían "inyectados" desde la vista principal (que sí generas en servidor).
Un saludo & gracias por comentar.
buen articulo me sirvio de mucho y lo dificil que es pillar algo en español me sorprendio de sobremanera tambien. como en mi link tenia partes que le paso desde el modelo (ya que esto necesitaba para hacer paginacion con pagedlist) yo termine haciendo algo asi
@Html.ActionLink("|Siguiente >", "Index", new { pagina = Model.PageNumber + 1, ordenacion = ViewBag.Ordenacion, filtro = ViewBag.FiltrO , empresa = "param-empresa", ruta = "param-ruta", ciudad = "param-ciudad" }, new { id = "mylinkSig" })
$(function () {
$('#mylinkFirst').click(function () {
var empresa = $("#empresa").val();
var ruta = $("#ruta").val();
var ciudad = $("#ciudad").val();
alert(empresa + "first");
this.href = this.href.replace("param-empresa", encodeURIComponent(empresa))
.replace("param-ruta", encodeURIComponent(ruta))
.replace("param-ciudad", encodeURIComponent(ciudad));
});
});
Muy bueno, el problema es cuando sacamos todo el codigo js a un archivo .js externo, con estas soluciones estariamos necesitando una variable en la vista asociada al .js por cada accion de cada controlador que utilice dicha vista, cosa que queda bastante desprolija, una solución que he leido a este problema es crear un var masterpath en la master page con la url del proyecto y de ahi en mas concatenar el resto de la ruta hacia la accion, con esto evitamos esos centenares de variables en las vistas definiendo las rutas.
Hola @anónimo!
Bueno, es lo que comentábamos: si concatenas las rutas estás introduciendo, al fin y al cabo, una dependencia bastante dura respecto al contenido de la tabla de rutas. Si estás seguro de que ésta no va a cambiar puede ser una forma sencilla de implementarlo, pero en cualquier caso siempre arriesgada.
Saludos!
Buenos dias.
No soy informatico y agradeceria si poseis ayudarme. Me gustaria mostrar la ultima imagen de radar de lluvia. El link se actualiza cada 10 minutos. Es el siguiente.
http://www.aemet.es/imagenes_d/eltiempo/observacion/radar/201504061150_r8ba.gif
Podeis hacerme el scrip?
Es ilegal publicar esta imagen en un blog?
Si, pues yo queria preguntar si es posible enviar mas de dos parametros. Estoy haciendo pruebas con 3 y ...no hay forma de recibir los valroes en el método ....
Hola!
No hay motivos para que los ejemplos anteriores no funcionen con más de dos parámetros, es exactamente lo mismo. Aunque en el caso del árbol de expresión sólo se muestra aquí implementado para dos variables, en el proyecto de ejemplo se muestra cómo hacerlo con más.
Saludos!
Hola, si tengo un grid que se alimenta de una lista de objetos Persona, y dentro del grid tengo una columna "idPersona" con un link y quiero que cuando le den click en el link pase como parametro el objeto del cual se formo el row del grid? es posible?
Hola! Posible seguro que es, pero deberás buscar en la documentación del grid cómo obtener las propiedades del objeto para poder enviarlas. Es decir, cada grid funciona de forma diferente y deberás adaptarte a ella.
Saludos!
Buenas, muy buen post.. como dijeron mas arriba, al sacar esto a un archivo .js ya no serviría, cual seria la solución en ese caso?
Muchas gracias!
Hola,
en efecto, no podrías ejecutar estos helpers en un archivo .js externo. Tendrías varias opciones para conseguirlo, entre otras:
- La más habitual es generar con Action() las rutas sobre la vista .cshtml y pasarlas como parámetro a las funciones del .js que las necesiten.
- También podrías depositar las rutas en variables globales en el JavaScript de la vista, generando los valores con el helper Action(), y luego consumirlas desde el interior del .js externo. El problema es la dependencia tan frágil que genera esto entre ambos componentes.
Saludos!
Gracias tu aporte me ayudo a solucionar mi problema
Enviar un nuevo comentario