原文地址: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 class VitualPathHttpModule:IHttpModule
{
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);
}
}
{
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
public class VirtualPathFilter : Stream
{
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
}
{
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
<modules>
<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>
<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里面就不包含虚拟目录了,大功告成。
浙公网安备 33010602011771号