Warum wird meine ASP.NET-Web-API ActionFilterAttribute OnActionExecuting nicht ausgelöst?

72

Ich versuche zu implementieren, was hier zu sehen ist: http://www.piotrwalat.net/nhibernate-session-management-in-asp-net-web-api/, aber ich habe ein Problem mit meinem NhSessionManagementAttribute.

Ich habe auf meinem Haltepunkt gesetzt, um OnActionExecuting(HttpActionContext actionContext)zu sehen, ob die Funktion jemals aufgerufen wurde - war es nicht.

Ich habe meine global.asax.csDatei noch einmal überprüft und festgestellt, dass ich die Datei tatsächlich registriere ActionFiltermit:

GlobalConfiguration.Configuration.Filters.Add(new NhSessionManagementAttribute());

Ich habe auch sowohl meine Controller-Klasse selbst als auch ihre Aktionen mit dem Attribut ohne Erfolg dekoriert:

public class ClientsController : ApiController {
    static readonly ClientRepository repository = new ClientRepository();

    [NhSessionManagement]
    public IEnumerable<Client> GetAllClients() {
        return repository.GetAll();
    }

    [NhSessionManagement]
    public Client GetClient(int id) {
        Client client = repository.Get(id);
        if (client == null) {
            throw new HttpResponseException(
                new HttpResponseMessage(HttpStatusCode.NotFound)
            );
        }
        return client;
    }
}

Warum würde dieser Aktionsfilter keines der darin enthaltenen Ereignisse auslösen?

Schrägstrich
quelle

Antworten:

168

Wenn Sie in einem Projekt arbeiten, das sowohl MVC- als auch WebAPI-Assemblys enthält, können Sie den Namespace Ihres ActionFilterAttribute-Namespace überprüfen. Es ist ziemlich verwirrend, weil es unter beiden zwei ActionFilterAttributes gibt:

  • WebAPI: System.Web.Http.Filters
  • MVC: System.Web.Http.Mvc
Troy Dai
quelle
1
Für WebAPI sollte das Filterattribut System.Web.Http.Mvc verwendet werden. Richtig?
Neontapir
Ich habe versucht herauszufinden, warum mein ActionFilter in den letzten Stunden nicht funktioniert. Danke Troy! :)
Divyanshm
3
Das ActionFilterAttribute für WebApi befindet sich in der Assembly System.Web.Http.dll.
Frode Lillerud
4
MVC: System.Web.Http.Mvc -> System.Web.Mvc in einigen ASP.NET MVC-Versionen
Boj
4
Ich bin immer noch verwirrt. Warum ist System.Web.Http.Filters.ActionFilterAttribute für WebAPI nicht die richtige Wahl? Die Antwort besagt nur, dass der Namespace überprüft werden soll, und gibt an, dass es zwei gibt. Es wird nicht erklärt, warum Sie die WebAPI nicht verwenden würden.
AaronLS
34

Die obige Antwort hat mir definitiv geholfen - anderen Zeit zu sparen ... hier ist ausdrücklich der Unterschied.

Standard-MVC-Controller verwenden:

// System.Web.Mvc
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    base.OnActionExecuting(filterContext);
}

OData HTTP-Controller verwenden:

// System.Web.Http.Filters;
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    base.OnActionExecuted(actionExecutedContext);
}
ProVega
quelle
3
Und die System.Web.Http.Filters sind auch für WebApi. Wenn Sie Ninject verwenden, ist es wichtig zu beachten, dass sich die Filterbindungen auch in verschiedenen Bibliotheken für Mvc und Http befinden. Mvc - Ninject.Web.Mvc WebApi / Http - Ninject.Web.WebApi
Kent Fehribach
1
Tatsächlich sollten die verwendeten HTTP-Controller OnActionExecuting (HttpActionContext httpActionContext) anzeigen und dann base.OnActionExecuting (httpActionContext) aufrufen. OnActionExecuted () ist ebenfalls verfügbar.
GarDavis
6

Für alle anderen, die darauf stoßen, wird ActionFilterAttribute nicht ausgelöst, wenn Sie YourController.YourAction von Ihrem UnitTest aus aufrufen.

[TestMethod]
public void RevokeSiteAdmin_SessionOver()
{
    FakeDbContext db = new FakeDbContext();

    YourController controller = new YourController(db);
    var result = controller.YourAction();

    //Some Assertions
}

In der obigen Testmethode werden keine ActionFilterAttributes auf YourController.YourAction aufgerufen. Jedoch; Wenn Sie YourController.YourAction über einen Browser aufrufen, wird Ihr ActionFilterAttribute aufgerufen.

Dies gilt zumindest für WebApi, aber ich weiß nicht, ob dies für MVC gilt.

Johnie Karr
quelle
1

Hier ist die vollständige Implementierung:

public class AllowCrossSiteJsonAttribute : System.Web.Mvc.ActionFilterAttribute
{
    public override void OnActionExecuted(System.Web.Mvc.ActionExecutedContext filterContext)
    {
        if (filterContext.HttpContext != null && filterContext.HttpContext.Response != null && filterContext.HttpContext.Request != null && filterContext.HttpContext.Request.UrlReferrer != null)
        {
            var allowedCrossDomains = TypeSafeConfigurationManager.GetValueString("allowedCrossDomains", "none");
            var allowedHosts = allowedCrossDomains.Split(',');

            var requestHost =  filterContext.HttpContext.Request.UrlReferrer.GetLeftPart(UriPartial.Authority);
            if (allowedHosts.Contains(requestHost.ToLower()))
            {
                filterContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", requestHost);
            }
        }

        base.OnActionExecuted(filterContext);
    }
}
public class AllowCrossSiteJsonForWebApiAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null && actionExecutedContext.Request != null &&
            actionExecutedContext.Request.Headers.Referrer != null)
        {
            var allowedCrossDomains = TypeSafeConfigurationManager.GetValueString("allowedCrossDomains", "none");
            var allowedHosts = allowedCrossDomains.Split(',').ToList();

            var requestHost = actionExecutedContext.Request.Headers.Referrer.GetLeftPart(UriPartial.Authority);

            if (allowedHosts.Contains(requestHost.ToLower()))
            {
                actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", requestHost);
            }

            base.OnActionExecuted(actionExecutedContext);
        }
    }
}
AjitChahal
quelle
0

Für WebApi sollten Sie Microsoft.AspNet.WebApi.Core von Nuget installieren. Für MVC können Sie System.Web.MVC verwenden.

Baran
quelle
0

Mein Problem war viel einfacher:

Überprüfen Sie, ob Ihr Controller mit dekoriert ist <actionPreProcessActivitiesAttribute()> _

bendecko
quelle