// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Castle.MonoRail.Framework.Routing
{
using System;
using System.IO;
using System.Web;
using System.Web.Configuration;
using Castle.MonoRail.Framework.Adapters;
///
/// Pendent
///
public class RoutingModuleEx : IHttpModule
{
private static readonly RoutingEngine engine = new RoutingEngine();
private string defaultUrlExtension = ".castle";
///
/// Inits the specified app.
///
/// The app.
public void Init(HttpApplication app)
{
app.BeginRequest += OnBeginRequest;
try
{
HttpHandlersSection httpHandlersConfig =
(HttpHandlersSection) WebConfigurationManager.GetSection("system.web/httpHandlers");
foreach(HttpHandlerAction handlerAction in httpHandlersConfig.Handlers)
{
if (typeof(MonoRailHttpHandlerFactory).IsAssignableFrom(Type.GetType(handlerAction.Type)))
{
if (handlerAction.Path.StartsWith("*."))
{
defaultUrlExtension = handlerAction.Path.Substring(1);
break;
}
else if (handlerAction.Path == "*")
{
defaultUrlExtension = string.Empty;
}
}
}
}
catch
{
//just swallow and keep on using .castle as the default.
}
}
///
/// Disposes of the resources (other than memory)
/// used by the module that implements .
///
public void Dispose()
{
}
///
/// Called when [begin request].
///
/// The sender.
/// The instance containing the event data.
public void OnBeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
HttpRequest request = context.Request;
HttpResponse response = context.Response;
if (File.Exists(request.PhysicalPath))
{
return; // Possibly requesting a static file, so we skip routing altogether
}
RouteMatch match =
engine.FindMatch(StripAppPathFrom(request.FilePath, request.ApplicationPath) + request.PathInfo,
new RouteContext(new RequestAdapter(request), response, request.ApplicationPath, context.Items));
if (match == null || response.StatusCode == 301 || response.StatusCode == 302)
{
return;
}
string mrPath = CreateMonoRailPath(match);
string url = request.RawUrl;
string paramsAsQueryString = "";
int queryStringIndex = url.IndexOf('?');
if (queryStringIndex != -1)
{
paramsAsQueryString = url.Substring(queryStringIndex + 1);
}
if (paramsAsQueryString.Length != 0)
{
context.RewritePath(mrPath, request.PathInfo, paramsAsQueryString);
}
else
{
context.RewritePath(mrPath);
}
context.Items.Add(RouteMatch.RouteMatchKey, match);
}
private string StripAppPathFrom(string path, string applicationPath)
{
if (applicationPath.Length != 1)
{
return path.Substring(applicationPath.Length);
}
return path;
}
private string CreateMonoRailPath(RouteMatch match)
{
if (!match.Parameters.ContainsKey("controller"))
{
throw new MonoRailException(
"Parameter 'controller' is not optional. Check your routing rules to make " +
"sure this parameter is being added to the RouteMatch");
}
if (!match.Parameters.ContainsKey("action"))
{
throw new MonoRailException(
"Parameter 'action' is not optional. Check your routing rules to make " +
"sure this parameter is being added to the RouteMatch");
}
string controller = match.Parameters["controller"];
string area = match.Parameters.ContainsKey("area") ? match.Parameters["area"] : null;
string action = match.Parameters["action"];
if (area != null)
{
return "~/" + area + "/" + controller + "/" + action + defaultUrlExtension;
}
else
{
return "~/" + controller + "/" + action + defaultUrlExtension;
}
}
///
/// Gets the engine.
///
/// The engine.
public static RoutingEngine Engine
{
get { return engine; }
}
}
}