2012年4月30日月曜日

Web APIでのSession利用

いやもうまじで。そんなことしなくていいと思うんですけど。ステートレスでやればいいと思うんですけど。

c# - LinqToEntitiesDataController MVC 4 Single Page Application - Session variable - Stack Overflow

普通にやるとApiControllerってHttpContext.Curret.Sessionはnullですね。なぜかというと、Web API利用時にRouteに登録するHttpControllerRouteHandlerのGetHttpHandlerでは、IRequiresSessionStateインターフェース指定のないHttpControllerHandlerが使われているからです。

デスデス。それでいいと思います。

でも、どーしても使いたい、っていうなら、そーですね。IRequiresSessionStateを付けたものを用意しましょう。

public class SessionHttpControllerRouteHandler : HttpControllerRouteHandler
{
    protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
    {
        return new SessionHttpControllerHandler(requestContext.RouteData);
    }
}

public class SessionHttpControllerHandler : HttpControllerHandler, IRequiresSessionState
{
    public SessionHttpControllerHandler(RouteData routeData) : base(routeData) { }
}

このHttpControllerRouteHandlerをRouteTable登録に利用する。

routes.Add("SessionApis",
	new HttpWebRoute(
		url: "api/{controller}/{id}",
		defaults: new RouteValueDictionary(new {id = RouteParameter.Optional}),
		routeHandler: new SessionHttpControllerRouteHandler()
));

これだけ。

Web APIのデフォルトプロジェクトテンプレートで作成したHomeControllerのIndexでSessionに値を入れて、ValuesControllerのGetで参照してみる。

public class HomeController : Controller
{
	public ActionResult Index()
	{
		Session["message"] = "from Controller";
		return View();
	}
public class ValuesController : ApiController
{
	// GET /api/values
	public IEnumerable<string> Get()
	{

		var message = HttpContext.Current.Session["message"] + "";
		return new string[] { "value1", "value2", message };
	}

実行して、/api/valuesにアクセスしてみる。

sessionapi

ねー。

ちなみにLinqToEntitiesDataControllerはAreaRegistrationだから、そっちでRouteTableに登録しましょう。

っていうか、是非使わないような設計で。