web-dev-qa-db-fra.com

MVC 3: Comment rendre une vue sans sa page de présentation lorsqu’il est chargé via ajax?

J'apprends à propos de Progressive Enhancement et j'ai une question à propos des vues AJAX. Dans mon projet MVC 3, j'ai une page de présentation, une page de démarrage (viewstart) et deux vues en clair.

La page viewstart se trouve à la racine du dossier Vues et s'applique donc à toutes les vues. Il spécifie que toutes les vues doivent utiliser _Layout.cshtml pour leur page de présentation. La page de présentation contient deux liens de navigation, un pour chaque vue. Les liens utilisent @Html.ActionLink() pour se rendre à la page.

Maintenant, j'ai ajouté jQuery et je veux détourner ces liens et utiliser Ajax pour charger leur contenu sur la page de manière dynamique.

<script type="text/javascript">
    $(function () {
        $('#theLink').click(function () {
            $.ajax({
                url: $(this).attr('href'),
                type: "GET",
                success: function (response) {
                    $('#mainContent').html(response);
                }
            });
            return false;
        });
    });
</script>

Je peux penser à cela de deux manières, mais je n'aime pas particulièrement l'une ou l'autre:

1) Je peux prendre tout le contenu de la vue et le placer dans une vue partielle, puis demander à la vue principale d'appeler la vue partielle lorsqu'elle est rendue. De cette façon, en utilisant Request.IsAjaxRequest() dans le contrôleur, je peux renvoyer View() ou _ PartialView() en fonction du fait que la requête est ou non une requête Ajax. Je ne peux pas retourner la vue normale à la requête Ajax car elle utiliserait alors la page de présentation et une seconde copie de la page de présentation serait injectée. Cependant, cela ne me plaît pas car cela me force à créer des vues vides contenant juste une @{Html.RenderPartial();} pour les requêtes GET standard.

    public ActionResult Index()
    {
        if (Request.IsAjaxRequest())
            return PartialView("partialView");
        else
            return View();
    }

Dans Index.cshtml, procédez comme suit:

@{Html.RenderPartial("partialView");}

2) Je peux supprimer la désignation de la structure de _viewstart et la spécifier manuellement lorsque la demande n'est pas Ajax:

    public ActionResult Index()
    {
        if (Request.IsAjaxRequest())
            return View(); // Return view with no master.
        else
            return View("Index", "_Layout"); // Return view with master.
    }

Quelqu'un a-t-il une meilleure suggestion? Est-il possible de retourner une vue sans sa page de disposition? Il serait beaucoup plus facile de dire explicitement "n'incluez pas votre mise en page" s'il s'agit d'une demande ajax, plutôt que d'inclure explicitement la mise en page si ce n'est pas une ajax.

153
Chev

Dans ~/Views/ViewStart.cshtml:

@{
    Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
}

et dans le contrôleur:

public ActionResult Index()
{
    return View();
}
253
Darin Dimitrov

Il suffit de mettre le code suivant en haut de la page

@{
    Layout = "";
}
89
roncansan

Je préfère et utilise votre option n ° 1. Je n'aime pas le n ° 2 car pour moi View() implique que vous retourniez une page entière. Une fois que le moteur de vue est terminé, la page HTML doit être complète et valide. PartialView() a été créé pour renvoyer des morceaux de code HTML arbitraires.

Je ne pense pas que ce soit un gros problème d'avoir une vue qui appelle seulement une partie. C'est encore sec, et vous permet d'utiliser la logique du partiel dans deux scénarios.

Beaucoup de gens n'aiment pas fragmenter les chemins d'appels de leurs actions avec Request.IsAjaxRequest(), et je peux l'apprécier. Mais IMO, si tout ce que vous faites est de décider s'il faut appeler View() ou PartialView(), alors la branche n’est pas un gros problème et est facile à maintenir (et à tester). Si vous vous trouvez en train d'utiliser IsAjaxRequest() pour déterminer une grande partie du déroulement de votre action, il est probablement préférable d'effectuer une action séparée AJAX.

13
Matt Greer

Créez deux présentations: 1. présentation vide, 2. mise en page principale et ensuite écrire dans le fichier _viewStart ce code:

@{
if (Request.IsAjaxRequest())
{
    Layout = "~/Areas/Dashboard/Views/Shared/_emptyLayout.cshtml";
}
else
{
    Layout = "~/Areas/Dashboard/Views/Shared/_Layout.cshtml";
}}

bien sûr, ce n'est peut-être pas la meilleure solution

13
Arash Karami

Vous n'avez pas à créer une vue vide pour cela.

Dans le contrôleur:

if (Request.IsAjaxRequest())
  return PartialView();
else
  return View();

renvoyer un PartialViewResult remplacera la définition de présentation lors du rendu de la réponse.

7
Souhaieb Besbes

Avec ASP.NET 5, aucune variable de requête n'est plus disponible. Vous pouvez y accéder maintenant avec Context.Request

De plus, il n'y a plus de méthode IsAjaxRequest (), vous devez l'écrire vous-même, par exemple dans Extensions\HttpRequestExtensions.cs.

using System;
using Microsoft.AspNetCore.Http;

namespace Microsoft.AspNetCore.Mvc
{
    public static class HttpRequestExtensions
    {
        public static bool IsAjaxRequest(this HttpRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            return (request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest");
        }
    }
}

Je cherche depuis un moment sur ce sujet et espère que cela aidera d’autres aussi;)

Ressource: https://github.com/aspnet/AspNetCore/issues/2729

1
Drotak