Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API Action Filter - Controller.TempData equivalent?

In my System.Web.Mvc Action filters I previously used TempData to store an instance of my unitOfWork service like so:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    filterContext.Controller.TempData[UnitOfWorkRequestKey] = UnitOfWork;
    UnitOfWork.Begin();
}

then to commit the transaction I retreived it from temp data like this..

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    var unitOfWork = (IUnitOfWork)filterContext.Controller.TempData[UnitOfWorkRequestKey];
    try
    {
        if (filterContext.Exception == null)
        {
            unitOfWork.Complete();
        }
    }
    finally
    {
        unitOfWork.Dispose();
        filterContext.Controller.TempData[UnitOfWorkRequestKey] = null;
    }
}

So my question is:
In the System.Web.Http Web Api Action Filter (using HttpActionContext) - is there an equivalent location to store my instance of a service, so I can retrieve the same instance when the action has executed?

like image 578
jonho Avatar asked Nov 30 '22 13:11

jonho


1 Answers

In the System.Web.Http Web Api Action Filter (using HttpActionContext) - is there an equivalent location to store my instance of a service, so I can retrieve the same instance when the action has executed?

No, there isn't. The whole point of an API is that it should be stateless. That's rule number 1. If you need to use Session or TempData in an API you are probably doing something very wrong from a design perspective.

Also you shouldn't be using TempData in your MVC application for this task. TempData is used when you need to persist information between more than one request. In your case it is the same request. So you should have used the HttpContext to store this information:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    filterContext.HttpContext.Items[UnitOfWorkRequestKey] = UnitOfWork;
}

and then:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    var unitOfWork = (IUnitOfWork) filterContext.HttpContext.Items[UnitOfWorkRequestKey];
    try
    {
        if (filterContext.Exception == null)
        {
            unitOfWork.Complete();
        }
    }
    finally
    {
        unitOfWork.Dispose();
        filterContext.Controller.TempData[UnitOfWorkRequestKey] = null;
    }
}

Alright, now that we have fixed your MVC application here's how to achieve the same in the Web API using the Request.Properties collection:

public override void OnActionExecuting(HttpActionContext actionContext)
{
    actionContext.Request.Properties[UnitOfWorkRequestKey] = UnitOfWork;
}

and then:

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    var unitOfWork = (IUnitOfWork) actionExecutedContext.Request.Properties[UnitOfWorkRequestKey];
    try
    {
        if (actionExecutedContext.Exception == null)
        {
            unitOfWork.Complete();
        }
    }
    finally
    {
        unitOfWork.Dispose();
    }
}
like image 141
Darin Dimitrov Avatar answered Dec 02 '22 02:12

Darin Dimitrov