Leer parámetros de la URL (query string) es una tarea fundamental en el desarrollo web con ASP.NET. Este artículo cubre todos los enfoques modernos y clásicos, desde Web Forms hasta ASP.NET Core y Minimal API.

¿Qué es una query string?

Una query string es la parte de una URL que viene después del signo ?. Contiene pares de clave-valor separados por &:

https://ejemplo.com/buscar?termino=asp.net&pagina=2&orden=fecha

En este ejemplo:

  • termino = asp.net
  • pagina = 2
  • orden = fecha

ASP.NET Web Forms (clásico)

Request.QueryString

// URL: https://ejemplo.com/pagina.aspx?id=42&nombre=producto

// Obtener un solo parámetro
string id = Request.QueryString["id"];        // "42"
string nombre = Request.QueryString["nombre"]; // "producto"

// Verificar si existe antes de usar
if (!string.IsNullOrEmpty(Request.QueryString["id"]))
{
    int productoId = int.Parse(Request.QueryString["id"]);
    // Usar el ID...
}

Uso en Page_Load

protected void Page_Load(object sender, EventArgs e)
{
    string categoria = Request.QueryString["cat"];
    
    if (!string.IsNullOrEmpty(categoria))
    {
        lblCategoria.Text = Server.HtmlEncode(categoria);
        CargarProductos(categoria);
    }
}

Seguridad: Siempre usa Server.HtmlEncode() al mostrar valores de query string en la página para prevenir ataques XSS (Cross-Site Scripting).

ASP.NET MVC

Enlace de modelo automático

En MVC, el framework vincula automáticamente los parámetros de la URL a los parámetros del método de acción:

// URL: /Productos/Buscar?termino=laptop&pagina=1
public ActionResult Buscar(string termino, int pagina = 1)
{
    // 'termino' = "laptop", 'pagina' = 1
    var resultados = _servicio.Buscar(termino, pagina);
    return View(resultados);
}

Acceso directo a QueryString

public ActionResult Detalle()
{
    string id = Request.QueryString["id"];
    // O en MVC, preferiblemente:
    string id2 = Request["id"];
    
    return View();
}

ASP.NET Core

Atributo [FromQuery]

// URL: /api/productos?categoria=electronica&precioMin=100&precioMax=500

[HttpGet]
public IActionResult ListarProductos(
    [FromQuery] string categoria,
    [FromQuery] decimal? precioMin,
    [FromQuery] decimal? precioMax)
{
    // Los parámetros se enlazan automáticamente desde la query string
    var productos = _repo.Filtrar(categoria, precioMin, precioMax);
    return Ok(productos);
}

Enlace con objeto de consulta

Para múltiples parámetros, usa una clase:

public class FiltroProducto
{
    public string Categoria { get; set; }
    public decimal? PrecioMin { get; set; }
    public decimal? PrecioMax { get; set; }
    public int Pagina { get; set; } = 1;
    public int TamañoPagina { get; set; } = 20;
}

[HttpGet]
public IActionResult Listar([FromQuery] FiltroProducto filtro)
{
    // Todos los parámetros de la URL se mapean a las propiedades del objeto
    var resultados = _repo.Filtrar(filtro);
    return Ok(resultados);
}

Acceso directo a HttpContext

public IActionResult Index()
{
    // Acceso directo sin enlace de modelo
    string valor = HttpContext.Request.Query["parametro"];
    
    // Verificar si existe
    if (HttpContext.Request.Query.ContainsKey("modo"))
    {
        string modo = HttpContext.Request.Query["modo"];
    }
    
    return View();
}

Minimal API (ASP.NET Core 6+)

var app = WebApplication.CreateBuilder(args).Build();

// Los parámetros de la URL se enlazan automáticamente
app.MapGet("/buscar", (string termino, int pagina = 1) =>
{
    return Results.Ok(new { Termino = termino, Pagina = pagina });
});

// Con [FromQuery] explícito
app.MapGet("/filtrar", ([FromQuery] string categoria, [FromQuery] int? limite) =>
{
    return Results.Ok(new { Categoria = categoria, Limite = limite ?? 10 });
});

app.Run();

Patrón ReturnUrl (redirección post-login)

Un caso de uso muy común es la URL de retorno después del inicio de sesión:

// URL: /Cuenta/Login?ReturnUrl=%2Fpanel%2Fconfiguracion

[HttpPost]
public IActionResult Login(LoginViewModel modelo, string returnUrl = null)
{
    if (ModelState.IsValid && AutenticarUsuario(modelo))
    {
        // IMPORTANTE: Validar que la URL sea local
        if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
        {
            return Redirect(returnUrl);
        }
        
        return RedirectToAction("Index", "Panel");
    }
    
    return View(modelo);
}

Prevención de redirecciones abiertas

Nunca hagas esto:

// PELIGROSO — vulnerable a redirección abierta
return Redirect(Request.QueryString["ReturnUrl"]);

Siempre valida antes de redirigir:

// SEGURO — valida que la URL sea local
string returnUrl = Request.Query["ReturnUrl"];
if (Url.IsLocalUrl(returnUrl))
{
    return Redirect(returnUrl);
}
return RedirectToAction("Index", "Home");

Un atacante podría usar ?ReturnUrl=https://sitio-malicioso.com para dirigir a los usuarios a un sitio de phishing.

Lectura con JavaScript

Para leer parámetros de la URL en el lado del cliente:

URLSearchParams (moderno)

// URL: https://ejemplo.com/pagina?termino=busqueda&lang=es

const params = new URLSearchParams(window.location.search);

// Obtener un parámetro
const termino = params.get('termino');  // "busqueda"
const lang = params.get('lang');        // "es"

// Verificar si existe
if (params.has('termino')) {
    console.log('Buscando:', params.get('termino'));
}

// Iterar todos los parámetros
for (const [clave, valor] of params) {
    console.log(`${clave} = ${valor}`);
}

Construir URLs con parámetros

const url = new URL('https://ejemplo.com/api/productos');
url.searchParams.set('categoria', 'electronica');
url.searchParams.set('pagina', '1');
console.log(url.toString());
// "https://ejemplo.com/api/productos?categoria=electronica&pagina=1"

Buenas prácticas

  1. Valida siempre los parámetros de entrada antes de usarlos
  2. Codifica la salida con HtmlEncode al mostrar valores en HTML
  3. Usa tipos fuertemente tipados en lugar de strings cuando sea posible
  4. Proporciona valores predeterminados para parámetros opcionales
  5. Verifica nulos antes de conversiones de tipo
  6. Nunca confíes en valores de la URL para operaciones sensibles sin validación

Solución de problemas

El parámetro siempre es null

  • Verifica que el nombre del parámetro coincide exactamente (distingue mayúsculas/minúsculas)
  • Asegúrate de que el ? está presente en la URL
  • Confirma que no hay un error de codificación en caracteres especiales

Caracteres especiales no se leen correctamente

Usa Uri.UnescapeDataString() para decodificar:

string valor = Uri.UnescapeDataString(Request.Query["texto"]);

Artículos relacionados