在web api層取得OwinContext

本篇文章介紹在web api層可以取得或設定OwinContextOwinEnvironment,來與middleware層互相溝通,

並介紹簡易的ActionAttribute的擴充方式

在OWIN上使用web api時,有時候就是想要共用一些在owin裡面才會出現的資訊,例如owincontext.environment這個歡樂的Dictionary,只要能夠得到這個Dictionary,那麼在middleware層與web api層就能互相溝通了!

其實在web api層取到HttpRequestMessage型態的Request是可以撈到OwinContext的,首先在NuGet加入Microsoft.AspNet.WebApi.Owin

接著在你的web api上引用System.Net.Http,就可以使用System.Net.Http提供的HttpRequestMessage靜態擴充:

  • public static IOwinContext GetOwinContext(this HttpRequestMessage request);
  • public static IDictionary<string, object> GetOwinEnvironment(this HttpRequestMessage request);
  • public static void SetOwinContext(this HttpRequestMessage request, IOwinContext context);
  • public static void SetOwinEnvironment(this HttpRequestMessage request, IDictionary<string, object> environment);

以下舉一個小例子示範在web api使用GetOwinEnvironment()來取得environment:

[RoutePrefix("api/daddy")]
public class DaddyController : ApiController
{
    // Get
    [Route("")]
    [HttpGet]
    public IHttpActionResult Get()
    {
        return Ok(Request.GetOwinEnvironment()["myenvironment.daddy"].toString());
    }
}

而不只web api,自行另外撰寫的ActionAttribute也可以用一樣的方式取得context或environment,以下範例程式碼為代表如果environment中key為myenvironment.daddy的值為假就傳回400(Bad Request)的response,代表這個request是有問題的

public class DaddyLoveMomFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        #region Contracts

        if (actionContext == null) throw new ArgumentNullException("actionContext");

        #endregion

        bool daddyLoveMon = true;
        if (bool.TryParse(actionContext.Request.GetOwinEnvironment()["myenvironment.daddy"].ToString(), out daddyLoveMe) == false)
        {
            daddyLoveMon = true;
        }

        if(daddyLoveMon == false)
        {
            throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
    }
}

若要使用以上的ActionAttribute在controller上的話,可以將[DaddyLoveMomFilter]放在controller的class上面或是method的上面。

將DaddyLoveMomFilter放在class上代表這個controller全部都要符合DaddyLoveMomFilter的標準;放在method上則代表這個action要符合DaddyLoveMomFilter的標準。

[RoutePrefix("api/daddy")]
[DaddyLoveMomFilter]
public class DaddyController : ApiController
{
    // Get
    [Route("")]
    [HttpGet]
    public IHttpActionResult Get()
    {
        return Ok(Request.GetOwinEnvironment()["myenvironment.daddy"].toString());
    }
}