web-dev-qa-db-fra.com

Y at-il un attribut relatif à AJAX être défini pour les actions du contrôleur ASP.NET MVC?

Je souhaite utiliser des vues partielles avec les appels AJAX dans ASP.NET MVC, et c'est la première fois que je l'utilise. Je viens de chercher pour voir s'il y a quelque chose de spécial que je devrais savoir à l'avance, et l'un d'entre eux qui m'intrigue est de voir si un attribut spécial doit être défini ou s'il est lié aux appels AJAX ? Quelque chose comme [ChildActionOnly] ou [HttpGet]

44
Saeed Neamati

Je ne pense pas qu'il existe un attribut intégré pour ajax mais ce n'est pas trop difficile d'en créer un. vous pouvez créer un filtre AjaxOnly comme

public class AjaxOnlyAttribute : ActionMethodSelectorAttribute 
    {
        public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
        {
            return controllerContext.RequestContext.HttpContext.Request.IsAjaxRequest();
        }
    }

et décorer vos méthodes d'action comme

[AjaxOnly]
public ActionResult ajaxMethod()
{

}

Regardez cet article pour une autre façon de mettre en oeuvre cet attribut

79

ASP.NET MVC fournit une méthode d'extension pour vérifier si une requête est une requête Ajax. Vous pouvez l'utiliser pour décider si vous souhaitez renvoyer une vue partielle ou un résultat JSON au lieu d'une vue normale.

if (Request.IsAjaxRequest())
{
    return PartialView("name");
}
return View();

Pour limiter une méthode d'action aux appels Ajax uniquement, vous pouvez écrire un attribut personnalisé. En cas de demande normale, ce filtre renverra une exception http 404 non trouvée.

[AttributeUsage(AttributeTargets.Method)]
public class AjaxOnlyAttribute : ActionFilterAttribute
{
     public override void OnActionExecuting(ActionExecutingContext filterContext)
     {
        if (!filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.HttpContext.Response.StatusCode = 404;
            filterContext.Result = new HttpNotFoundResult();
        }
        else
        {
            base.OnActionExecuting(filterContext);
        }
     }
}

vous pouvez l'utiliser comme ça:

[AjaxOnly]
public ActionResult Index() {
    // do something awesome
}
17
tehshin

La réponse de Muhammad est une retombée qui vous permet de préciser qu'il ne doit pas s'agir non plus d'une demande ajax:

using System.Web.Mvc;
public class AjaxAttribute : ActionMethodSelectorAttribute
{
    public bool ajax { get; set; }
    public AjaxAttribute() { ajax = true; }
    public AjaxAttribute(bool a) { ajax = a; }
    public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
    {
        return ajax == controllerContext.HttpContext.Request.IsAjaxRequest();
    }
}

Cela vous permet de faire des choses comme ...

[Ajax]
public PartialViewResult AjaxUpdatingPage() {
    return PartialView();
}

[Ajax(false)]
public ViewResult NotAjaxUpdatingPage() {
    return View();
}
4
Pluto

ma solution suit l'implémentation [ChildActionOnly]:

public class AjaxOnlyAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
            throw new ArgumentNullException("filterContext");
        if (!filterContext.HttpContext.Request.IsAjaxRequest())
            throw new InvalidOperationException(string.Format(
                CultureInfo.CurrentCulture, 
                "The action '{0}' is accessible only by an ajax request.", 
                filterContext.ActionDescriptor.ActionName
            ));
    }
}
2
sanjuro

Pour ceux qui recherchent une solution .NET Core, c'est un peu plus compliqué, car IsAjaxRequest() n'est plus disponible. 

Vous trouverez ci-dessous le code que j'ai utilisé en production sur plusieurs projets et qui a de l'effet.

public class AjaxOnlyAttribute : ActionMethodSelectorAttribute
{
  public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor actionDescriptor)
  {
    if(routeContext.HttpContext.Request.Headers != null &&
      routeContext.HttpContext.Request.Headers.ContainsKey("X-Requested-With") &&
      routeContext.HttpContext.Request.Headers.TryGetValue("X-Requested-With", out StringValues requestedWithHeader))
    {
      if(requestedWithHeader.Contains("XMLHttpRequest"))
      {
        return true;
      }
    }

    return false;
  }
}
0
pimbrouwers