Compartir a través de


Parte 10. Examen de los métodos Details y Delete de una aplicación de ASP.NET Core

Nota:

Esta no es la versión más reciente de este artículo. Para la versión actual, consulta la versión .NET 8 de este artículo.

Advertencia

Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulta la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulta la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulta la versión .NET 8 de este artículo.

Por Rick Anderson

Abra el controlador Movie y examine el método Details:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

El motor de scaffolding de MVC que creó este método de acción agrega un comentario en el que se muestra una solicitud HTTP que invoca el método. En este caso se trata de una solicitud GET con tres segmentos de dirección URL, el controlador Movies, el método Details y un valor id. Recuerde que estos segmentos se definen en Program.cs.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

EF facilita el proceso de búsqueda de datos mediante el método FirstOrDefaultAsync. Una característica de seguridad importante integrada en el método es que el código comprueba que el método de búsqueda haya encontrado una película antes de intentar hacer nada con ella. Por ejemplo, un hacker podría introducir errores en el sitio cambiando la dirección URL creada por los vínculos de http://localhost:{PORT}/Movies/Details/1 a algo parecido a http://localhost:{PORT}/Movies/Details/12345, o algún otro valor que no represente una película real. Si no comprobara una película null, la aplicación generaría una excepción.

Examine los métodos Delete y DeleteConfirmed.

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{

    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    var movie = await _context.Movie.FindAsync(id);
    if (movie != null)
    {
        _context.Movie.Remove(movie);
    }

    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

Tenga en cuenta que el método HTTP GET Delete no elimina la película especificada, sino que devuelve una vista de la película donde puede enviar (HttpPost) la eliminación. La acción de efectuar una operación de eliminación en respuesta a una solicitud GET (o con este propósito efectuar una operación de edición, creación o cualquier otra operación que modifique los datos) genera una vulnerabilidad de seguridad.

El método [HttpPost] que elimina los datos se denomina DeleteConfirmed para proporcionar al método HTTP POST una firma o nombre únicos. Las dos firmas de método se muestran a continuación:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{

Common Language Runtime (CLR) requiere métodos sobrecargados para disponer de una firma de parámetro única (mismo nombre de método, pero lista de parámetros diferente). En cambio, aquí necesita dos métodos Delete (uno para GET y otro para POST) que tienen la misma firma de parámetro (ambos deben aceptar un número entero como parámetro).

Hay dos enfoques para este problema. Uno consiste en proporcionar nombres diferentes a los métodos, que es lo que hizo el mecanismo de scaffolding en el ejemplo anterior. Pero esto implica un pequeño problema: ASP.NET asigna los segmentos de una dirección URL a los métodos de acción por nombre, de modo que si cambia el nombre de un método, el enrutamiento seguramente no podrá encontrar dicho método. La solución es la que ve en el ejemplo, que consiste en agregar el atributo ActionName("Delete") al método DeleteConfirmed. Ese atributo efectúa la asignación para el sistema de enrutamiento para que una dirección URL que incluya /Delete/ para una solicitud POST busque el método DeleteConfirmed.

Otra solución alternativa común para los métodos que tienen nombres y firmas idénticos consiste en cambiar la firma del método POST artificialmente para incluir un parámetro adicional (sin usar). Es lo que hicimos en una publicación anterior, cuando agregamos el parámetro notUsed. Podría hacer lo mismo aquí para el método [HttpPost] Delete:

// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

Publicar en Azure

Para obtener información sobre la implementación en Azure, consulte Tutorial: Compilación de una aplicación ASP.NET Core y SQL Database en Azure App Service.

Patrones de aplicación web confiable

Consulte El patrón de aplicación web confiable para .NET vídeos de YouTube y artículo para obtener una guía sobre cómo crear una aplicación moderna, confiable, eficaz, comprobable, rentable y escalable ASP.NET Core, ya sea desde cero o refactorizando una aplicación existente.

Abra el controlador Movie y examine el método Details:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

El motor de scaffolding de MVC que creó este método de acción agrega un comentario en el que se muestra una solicitud HTTP que invoca el método. En este caso se trata de una solicitud GET con tres segmentos de dirección URL, el controlador Movies, el método Details y un valor id. Recuerde que estos segmentos se definen en Program.cs.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

EF facilita el proceso de búsqueda de datos mediante el método FirstOrDefaultAsync. Una característica de seguridad importante integrada en el método es que el código comprueba que el método de búsqueda haya encontrado una película antes de intentar hacer nada con ella. Por ejemplo, un hacker podría introducir errores en el sitio cambiando la dirección URL creada por los vínculos de http://localhost:{PORT}/Movies/Details/1 a algo parecido a http://localhost:{PORT}/Movies/Details/12345, o algún otro valor que no represente una película real. Si no comprobara una película null, la aplicación generaría una excepción.

Examine los métodos Delete y DeleteConfirmed.

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{

    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    var movie = await _context.Movie.FindAsync(id);
    if (movie != null)
    {
        _context.Movie.Remove(movie);
    }

    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

Tenga en cuenta que el método HTTP GET Delete no elimina la película especificada, sino que devuelve una vista de la película donde puede enviar (HttpPost) la eliminación. La acción de efectuar una operación de eliminación en respuesta a una solicitud GET (o con este propósito efectuar una operación de edición, creación o cualquier otra operación que modifique los datos) genera una vulnerabilidad de seguridad.

El método [HttpPost] que elimina los datos se denomina DeleteConfirmed para proporcionar al método HTTP POST una firma o nombre únicos. Las dos firmas de método se muestran a continuación:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{

Common Language Runtime (CLR) requiere métodos sobrecargados para disponer de una firma de parámetro única (mismo nombre de método, pero lista de parámetros diferente). En cambio, aquí necesita dos métodos Delete (uno para GET y otro para POST) que tienen la misma firma de parámetro (ambos deben aceptar un número entero como parámetro).

Hay dos enfoques para este problema. Uno consiste en proporcionar nombres diferentes a los métodos, que es lo que hizo el mecanismo de scaffolding en el ejemplo anterior. Pero esto implica un pequeño problema: ASP.NET asigna los segmentos de una dirección URL a los métodos de acción por nombre, de modo que si cambia el nombre de un método, el enrutamiento seguramente no podrá encontrar dicho método. La solución es la que ve en el ejemplo, que consiste en agregar el atributo ActionName("Delete") al método DeleteConfirmed. Ese atributo efectúa la asignación para el sistema de enrutamiento para que una dirección URL que incluya /Delete/ para una solicitud POST busque el método DeleteConfirmed.

Otra solución alternativa común para los métodos que tienen nombres y firmas idénticos consiste en cambiar la firma del método POST artificialmente para incluir un parámetro adicional (sin usar). Es lo que hicimos en una publicación anterior, cuando agregamos el parámetro notUsed. Podría hacer lo mismo aquí para el método [HttpPost] Delete:

// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

Publicar en Azure

Para obtener información sobre la implementación en Azure, consulte Tutorial: Compilación de una aplicación ASP.NET Core y SQL Database en Azure App Service.

Patrones de aplicación web confiable

Consulte El patrón de aplicación web confiable para .NET vídeos de YouTube y artículo para obtener una guía sobre cómo crear una aplicación moderna, confiable, eficaz, comprobable, rentable y escalable ASP.NET Core, ya sea desde cero o refactorizando una aplicación existente.

Abra el controlador Movie y examine el método Details:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

El motor de scaffolding de MVC que creó este método de acción agrega un comentario en el que se muestra una solicitud HTTP que invoca el método. En este caso se trata de una solicitud GET con tres segmentos de dirección URL, el controlador Movies, el método Details y un valor id. Recuerde que estos segmentos se definen en Program.cs.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

EF facilita el proceso de búsqueda de datos mediante el método FirstOrDefaultAsync. Una característica de seguridad importante integrada en el método es que el código comprueba que el método de búsqueda haya encontrado una película antes de intentar hacer nada con ella. Por ejemplo, un hacker podría introducir errores en el sitio cambiando la dirección URL creada por los vínculos de http://localhost:{PORT}/Movies/Details/1 a algo parecido a http://localhost:{PORT}/Movies/Details/12345, o algún otro valor que no represente una película real. Si no comprobara una película null, la aplicación generaría una excepción.

Examine los métodos Delete y DeleteConfirmed.

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{

    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    var movie = await _context.Movie.FindAsync(id);
    if (movie != null)
    {
        _context.Movie.Remove(movie);
    }

    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

Tenga en cuenta que el método HTTP GET Delete no elimina la película especificada, sino que devuelve una vista de la película donde puede enviar (HttpPost) la eliminación. La acción de efectuar una operación de eliminación en respuesta a una solicitud GET (o con este propósito efectuar una operación de edición, creación o cualquier otra operación que modifique los datos) genera una vulnerabilidad de seguridad.

El método [HttpPost] que elimina los datos se denomina DeleteConfirmed para proporcionar al método HTTP POST una firma o nombre únicos. Las dos firmas de método se muestran a continuación:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{

Common Language Runtime (CLR) requiere métodos sobrecargados para disponer de una firma de parámetro única (mismo nombre de método, pero lista de parámetros diferente). En cambio, aquí necesita dos métodos Delete (uno para GET y otro para POST) que tienen la misma firma de parámetro (ambos deben aceptar un número entero como parámetro).

Hay dos enfoques para este problema. Uno consiste en proporcionar nombres diferentes a los métodos, que es lo que hizo el mecanismo de scaffolding en el ejemplo anterior. Pero esto implica un pequeño problema: ASP.NET asigna los segmentos de una dirección URL a los métodos de acción por nombre, de modo que si cambia el nombre de un método, el enrutamiento seguramente no podrá encontrar dicho método. La solución es la que ve en el ejemplo, que consiste en agregar el atributo ActionName("Delete") al método DeleteConfirmed. Ese atributo efectúa la asignación para el sistema de enrutamiento para que una dirección URL que incluya /Delete/ para una solicitud POST busque el método DeleteConfirmed.

Otra solución alternativa común para los métodos que tienen nombres y firmas idénticos consiste en cambiar la firma del método POST artificialmente para incluir un parámetro adicional (sin usar). Es lo que hicimos en una publicación anterior, cuando agregamos el parámetro notUsed. Podría hacer lo mismo aquí para el método [HttpPost] Delete:

// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

Publicar en Azure

Para obtener información sobre la implementación en Azure, consulte Tutorial: Compilación de una aplicación ASP.NET Core y SQL Database en Azure App Service.

Abra el controlador Movie y examine el método Details:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

El motor de scaffolding de MVC que creó este método de acción agrega un comentario en el que se muestra una solicitud HTTP que invoca el método. En este caso se trata de una solicitud GET con tres segmentos de dirección URL, el controlador Movies, el método Details y un valor id. Recuerde que estos segmentos se definen en Program.cs.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

EF facilita el proceso de búsqueda de datos mediante el método FirstOrDefaultAsync. Una característica de seguridad importante integrada en el método es que el código comprueba que el método de búsqueda haya encontrado una película antes de intentar hacer nada con ella. Por ejemplo, un hacker podría introducir errores en el sitio cambiando la dirección URL creada por los vínculos de http://localhost:{PORT}/Movies/Details/1 a algo parecido a http://localhost:{PORT}/Movies/Details/12345, o algún otro valor que no represente una película real. Si no comprobara una película null, la aplicación generaría una excepción.

Examine los métodos Delete y DeleteConfirmed.

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    var movie = await _context.Movie.FindAsync(id);
    _context.Movie.Remove(movie);
    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

Tenga en cuenta que el método HTTP GET Delete no elimina la película especificada, sino que devuelve una vista de la película donde puede enviar (HttpPost) la eliminación. La acción de efectuar una operación de eliminación en respuesta a una solicitud GET (o con este propósito efectuar una operación de edición, creación o cualquier otra operación que modifique los datos) genera una vulnerabilidad de seguridad.

El método [HttpPost] que elimina los datos se denomina DeleteConfirmed para proporcionar al método HTTP POST una firma o nombre únicos. Las dos firmas de método se muestran a continuación:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{

Common Language Runtime (CLR) requiere métodos sobrecargados para disponer de una firma de parámetro única (mismo nombre de método, pero lista de parámetros diferente). En cambio, aquí necesita dos métodos Delete (uno para GET y otro para POST) que tienen la misma firma de parámetro (ambos deben aceptar un número entero como parámetro).

Hay dos enfoques para este problema. Uno consiste en proporcionar nombres diferentes a los métodos, que es lo que hizo el mecanismo de scaffolding en el ejemplo anterior. Pero esto implica un pequeño problema: ASP.NET asigna los segmentos de una dirección URL a los métodos de acción por nombre, de modo que si cambia el nombre de un método, el enrutamiento seguramente no podrá encontrar dicho método. La solución es la que ve en el ejemplo, que consiste en agregar el atributo ActionName("Delete") al método DeleteConfirmed. Ese atributo efectúa la asignación para el sistema de enrutamiento para que una dirección URL que incluya /Delete/ para una solicitud POST busque el método DeleteConfirmed.

Otra solución alternativa común para los métodos que tienen nombres y firmas idénticos consiste en cambiar la firma del método POST artificialmente para incluir un parámetro adicional (sin usar). Es lo que hicimos en una publicación anterior, cuando agregamos el parámetro notUsed. Podría hacer lo mismo aquí para el método [HttpPost] Delete:

// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

Publicar en Azure

Para obtener información sobre la implementación en Azure, consulte Tutorial: Compilación de una aplicación ASP.NET Core y SQL Database en Azure App Service.

Abra el controlador Movie y examine el método Details:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

El motor de scaffolding de MVC que creó este método de acción agrega un comentario en el que se muestra una solicitud HTTP que invoca el método. En este caso se trata de una solicitud GET con tres segmentos de dirección URL, el controlador Movies, el método Details y un valor id. Recuerde que estos segmentos se definen en Startup.cs.

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

EF facilita el proceso de búsqueda de datos mediante el método FirstOrDefaultAsync. Una característica de seguridad importante integrada en el método es que el código comprueba que el método de búsqueda haya encontrado una película antes de intentar hacer nada con ella. Por ejemplo, un hacker podría introducir errores en el sitio cambiando la dirección URL creada por los vínculos de http://localhost:{PORT}/Movies/Details/1 a algo parecido a http://localhost:{PORT}/Movies/Details/12345, o algún otro valor que no represente una película real. Si no comprobara una película null, la aplicación generaría una excepción.

Examine los métodos Delete y DeleteConfirmed.

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    var movie = await _context.Movie.FindAsync(id);
    _context.Movie.Remove(movie);
    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

Tenga en cuenta que el método HTTP GET Delete no elimina la película especificada, sino que devuelve una vista de la película donde puede enviar (HttpPost) la eliminación. La acción de efectuar una operación de eliminación en respuesta a una solicitud GET (o con este propósito efectuar una operación de edición, creación o cualquier otra operación que modifique los datos) genera una vulnerabilidad de seguridad.

El método [HttpPost] que elimina los datos se denomina DeleteConfirmed para proporcionar al método HTTP POST una firma o nombre únicos. Las dos firmas de método se muestran a continuación:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{

Common Language Runtime (CLR) requiere métodos sobrecargados para disponer de una firma de parámetro única (mismo nombre de método, pero lista de parámetros diferente). En cambio, aquí necesita dos métodos Delete (uno para GET y otro para POST) que tienen la misma firma de parámetro (ambos deben aceptar un número entero como parámetro).

Hay dos enfoques para este problema. Uno consiste en proporcionar nombres diferentes a los métodos, que es lo que hizo el mecanismo de scaffolding en el ejemplo anterior. Pero esto implica un pequeño problema: ASP.NET asigna los segmentos de una dirección URL a los métodos de acción por nombre, de modo que si cambia el nombre de un método, el enrutamiento seguramente no podrá encontrar dicho método. La solución es la que ve en el ejemplo, que consiste en agregar el atributo ActionName("Delete") al método DeleteConfirmed. Ese atributo efectúa la asignación para el sistema de enrutamiento para que una dirección URL que incluya /Delete/ para una solicitud POST busque el método DeleteConfirmed.

Otra solución alternativa común para los métodos que tienen nombres y firmas idénticos consiste en cambiar la firma del método POST artificialmente para incluir un parámetro adicional (sin usar). Es lo que hicimos en una publicación anterior, cuando agregamos el parámetro notUsed. Podría hacer lo mismo aquí para el método [HttpPost] Delete:

// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

Publicar en Azure

Para obtener información sobre la implementación en Azure, consulte Tutorial: Compilación de una aplicación ASP.NET Core y SQL Database en Azure App Service.