原文地址:http://hongzhang.me/post/2011/06/11/godaddy-blogengine-virtualpath.aspx
Godaddy的虚拟主机支持多个域名,但是我再配置BlogEngine.NET的时候,发现生成的URL包含虚拟目录,如:http://mydomain/blog/...... 红色的blog就是我再主机上面建立的子目录,用于存放BlogEngine.NET的目录。如何不让blog显示在生成的URL中呢?
如果修改源代码,那么以后的升级会很麻烦。所以解决方法必须要做到可配置,对源代码修改最小化。我的思路是添加一个HttpModule,在 HttpModule中将所有的a标签里面包含虚拟目录名称的替换成空字符串。这样对源代码的修改只是在web.config里面多注册一个 HttpModule。
方法确定了,有个关键问题需要解决:如何在HttpModule中修改Http输出内容?方法就是使用HttpApplication.Response.Filter,自定义一个Filter,在Filter里面实现URL的分析和处理。
关键代码:
1.定义HttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
}
void context_ReleaseRequestState( object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
// 装配过滤器
application.Response.Filter = new VirtualPathFilter(application.Response.Filter, application);
}
}
2.定义自定义Filter:VirtualPathFilter
{
Stream responseStream;
long position;
HttpApplication context;
private VirtualPathFilter()
{
}
public VirtualPathFilter(Stream inputStream,HttpApplication inputContext)
{
responseStream = inputStream;
context = inputContext;
}
#region Write
public override void Write( byte [] buffer, int offset, int count)
{
string strContent = UTF8Encoding.UTF8.GetString(buffer);
string vitualPath = VirtualPathUtility.ToAbsolute(ConfigurationManager.AppSettings[ " BlogEngine.VirtualPath " ]);
if ( ! string .IsNullOrEmpty(vitualPath))
{
var vitualPath1 = vitualPath.TrimStart( ' / ' );
var vitualPath2 = vitualPath.TrimEnd( ' / ' );
var vitualPath3 = vitualPath.Trim( ' / ' );
string pattern = " <a[^<>]+href=\"[^>\"]* " + vitualPath3 + " [^>\"]*\" " ;
Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
var ms = reg.Matches(strContent);
List < string > values = new List < string > ();
foreach (Match item in ms)
{
var value = item.Value;
if (values.Contains(value))
{
continue ;
}
values.Add(value);
if (value.IndexOf(vitualPath) > - 1 )
{
value = value.Replace(vitualPath, " / " );
}
if (value.IndexOf(vitualPath1) > - 1 )
{
// othersite/blog/#NET -> #NET
value = value.Replace(vitualPath1, "" );
}
if (value.IndexOf(vitualPath2) > - 1 )
{
// /othersite/blog -> /
value = value.Replace(vitualPath2, " / " );
}
if (value.IndexOf(vitualPath3) > - 1 )
{
value = value.Replace(vitualPath3, "" );
}
strContent = strContent.Replace(item.Value, value);
}
}
responseStream.Write(UTF8Encoding.UTF8.GetBytes(strContent), offset, UTF8Encoding.UTF8.GetByteCount(strContent));
}
#endregion
#region Filter Overrides
public override bool CanRead
{
get
{
return true ;
}
}
public override bool CanSeek
{
get
{
return true ;
}
}
public override bool CanWrite
{
get
{
return true ;
}
}
public override void Close()
{
responseStream.Close();
}
public override void Flush()
{
responseStream.Flush();
}
public override long Length
{
get
{
return 0 ;
}
}
public override long Position
{
get
{
return position;
}
set
{
position = value;
}
}
public override int Read( byte [] buffer, int offset, int count)
{
return responseStream.Read(buffer, offset, count);
}
public override long Seek( long offset, SeekOrigin origin)
{
return responseStream.Seek(offset, origin);
}
public override void SetLength( long length)
{
responseStream.SetLength(length);
}
#endregion
}
3.在Web.config中注册HttpModule
< add name ="WwwSubDomainModule" type ="BlogEngine.Core.Web.HttpModules.WwwSubDomainModule, BlogEngine.Core" />
< add name ="UrlRewrite" type ="BlogEngine.Core.Web.HttpModules.UrlRewrite, BlogEngine.Core" />
< add name ="CompressionModule" type ="BlogEngine.Core.Web.HttpModules.CompressionModule, BlogEngine.Core" />
< add name ="ReferrerModule" type ="BlogEngine.Core.Web.HttpModules.ReferrerModule, BlogEngine.Core" />
< add name ="VitualPathModule" type ="BE.Extention.VitualPathHttpModule,BE.Extention" />
</ modules >
至此,BlogEngine.NET生成的URL里面就不包含虚拟目录了,大功告成。