1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.MonoRail
.Framework
19 using System
.Web
.SessionState
;
20 using Castle
.Core
.Logging
;
21 using Castle
.MonoRail
.Framework
.Adapters
;
24 /// Implements <see cref="IHttpHandler"/> to dispatch the web
26 /// <seealso cref="MonoRailHttpHandlerFactory"/>
28 public class MonoRailHttpHandler
: IHttpHandler
, IRequiresSessionState
30 /// <summary>Logger instance that won't be null, even when logging is disabled</summary>
31 private readonly ILogger logger
;
34 /// Constructs a <c>MonoRailHttpHandler</c>
36 /// <param name="logger"></param>
37 public MonoRailHttpHandler(ILogger logger
)
42 #region IHttpHandler implementation
47 /// <param name="context"></param>
48 public void ProcessRequest(HttpContext context
)
50 IRailsEngineContext mrContext
= EngineContextModule
.ObtainRailsEngineContext(context
);
58 public bool IsReusable
66 /// Performs the base work of MonoRail. Extracts
67 /// the information from the URL, obtain the controller
68 /// that matches this information and dispatch the execution
71 /// <param name="context"></param>
72 public virtual void Process(IRailsEngineContext context
)
74 ControllerLifecycleExecutor executor
=
75 (ControllerLifecycleExecutor
) context
.Items
[ControllerLifecycleExecutor
.ExecutorEntry
];
77 DefaultRailsEngineContext contextImpl
= (DefaultRailsEngineContext
) context
;
78 contextImpl
.ResolveRequestSession();
80 context
.Items
["mr.controller"] = executor
.Controller
;
81 context
.Items
["mr.flash"] = executor
.Controller
.Flash
;
82 context
.Items
["mr.propertybag"] = executor
.Controller
.PropertyBag
;
83 context
.Items
["mr.session"] = context
.Session
;
85 // At this point, the before filters were executed.
86 // So we just need to perform the secondary initialization
87 // and invoke the action
91 if (executor
.HasError
) // Some error happened
93 executor
.PerformErrorHandling();
97 executor
.ProcessSelectedAction();
102 if (logger
.IsErrorEnabled
)
104 logger
.Error("Error processing " + context
.Url
, ex
);
117 IControllerFactory controllerFactory
=
118 (IControllerFactory
) context
.GetService(typeof(IControllerFactory
));
120 controllerFactory
.Release(executor
.Controller
);
123 if (logger
.IsDebugEnabled
)
125 Controller controller
= executor
.Controller
;
127 logger
.DebugFormat("Ending request process for '{0}'/'{1}.{2}' Extension '{3}' with url '{4}'",
128 controller
.AreaName
, controller
.Name
, controller
.Action
, context
.UrlInfo
.Extension
, context
.UrlInfo
.UrlRaw
);
131 // Remove items from flash before leaving the page
132 context
.Flash
.Sweep();
134 if (context
.Flash
.HasItemsToKeep
)
136 context
.Session
[Flash
.FlashKey
] = context
.Flash
;
138 else if (context
.Session
.Contains(Flash
.FlashKey
))
140 context
.Session
.Remove(Flash
.FlashKey
);
146 /// Can be overriden so new semantics can be supported.
148 /// <param name="context"></param>
149 /// <returns></returns>
150 protected virtual UrlInfo
ExtractUrlInfo(IRailsEngineContext context
)
152 return context
.UrlInfo
;
156 /// Gets the current context.
158 /// <value>The current context.</value>
159 public static IRailsEngineContext CurrentContext
163 HttpContext context
= HttpContext
.Current
;
165 // Are we in a web request?
166 if (context
== null) return null;
168 return EngineContextModule
.ObtainRailsEngineContext(context
);