2011-07-02 14 views
41

Desidero utilizzare viste parziali con chiamate AJAX in ASP.NET MVC e questa è la prima volta che lo utilizzo. Ho appena cercato di vedere se c'è qualcosa di speciale che dovrei sapere in anticipo, e uno dei quali sono curioso di sapere, è vedere se c'è qualche attributo speciale che dovrebbe essere impostato o è collegato alle chiamate AJAX? Qualcosa come [ChildActionOnly] o [HttpGet]È stato impostato un attributo relativo a AJAX per le azioni del controller ASP.NET MVC?

risposta

71

Non penso che ci sia un attributo built-in per ajax ma non è troppo difficile crearne uno. è possibile creare AjaxOnly filtrare come

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

e decorare i vostri metodi d'azione come

[AjaxOnly] 
public ActionResult ajaxMethod() 
{ 

} 

Guarda this post per un altro modo di attuare questo attributo

+1

Come MVC sa che questa è davvero una richiesta AJAX.Usa qualche campo di intestazione HTTP personalizzato? A volte XmlHttpRequest non invia intestazioni personalizzate. –

+3

Usa l'intestazione 'X-Requested-With' e questa è l'intestazione che viene letta dal metodo' Request.IsAjaxRequest() '. –

+0

C'è un modo per fare qualcosa di simile con AttributeRouting? Implementa HttpRouteAttribute. – appsecguy

13

ASP.NET MVC fornisce un metodo di estensione per controllare se una richiesta è una richiesta Ajax. Puoi usarlo per decidere se vuoi restituire una vista parziale o un risultato JSON invece di una vista normale.

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

Per limitare un metodo di azione alle chiamate Ajax, è possibile solo scrivere un attributo personalizzato. In caso di una richiesta normale, questo filtro restituirà un'eccezione http non trovata 404.

[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); 
     } 
    } 
} 

è possibile utilizzarlo così:

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

C'è un [AjaxOnly] attributo fornito nel collezione ASP.NET MVC 3 Futures. Fa parte del sito ufficiale ASP.NET MVC Codeplex che fornisce funzionalità prima che vengano incluse ufficialmente in una versione futura di ASP.NET MVC.

È possibile scaricarlo here. Per utilizzarlo, aggiungere un riferimento all'assembly Microsoft.Web.Mvc incluso nel pacchetto di rilascio.

C'è una spiegazione dell'attributo nella pagina this, insieme a tutte le altre fantastiche funzioni che è possibile utilizzare.

2

mia soluzione segue la [ChildActionOnly] realizzazione:

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 
      )); 
    } 
} 
+0

+1 per fornire un'implementazione che può essere applicata a un intero controller (anziché applicarlo separatamente a ogni singolo metodo di azione, il che può essere piuttosto difficile). – xDisruptor

3

uno spin-off della risposta di Muhammad permettendo di specificare che non deve essere una richiesta AJAX così:

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(); 
    } 
} 

Questo ti permette di fare le cose come ...

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

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

Per chi cerca una soluzione .NET Core è ' s un po 'più coinvolto, come IsAjaxRequest() non è più disponibile.

Di seguito è riportato il codice che ho utilizzato in produzione su diversi progetti con grande effetto.

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; 
    } 
} 
Problemi correlati