我们公司的网站都是使用的是mvc
框架,最近有这样的需求.因为之前的一些东西在开始开发的时候写死了.比如静态资源地址或者别的站点的地址.但是最近改版的时候需要重新配置地址.如果全局搜索修改地址的话工作量太大.于是想着是否可以使用全局过滤器来重写Response
流来实现.下面给出解决方案.
具体就是重写ActionFilterAttribute
.然后为Response.Filter
重置为我们实现了我们业务需要的Filter.
首先创建过滤器.如下:
public class RewriteHttpsFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var response = filterContext.HttpContext.Response;
string IsRedirectToHttps = ConfigurationManager.AppSettings["IsRedirectToHttps"];
string IsRewriteToHttps = ConfigurationManager.AppSettings["IsRewriteToHttps"];
#if Release
if (!string.IsNullOrEmpty(IsRedirectToHttps) && IsRedirectToHttps == "1")
{
var request = filterContext.HttpContext.Request;
if (request.Url.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase))
{
string redirurl = request.Url.ToString().Replace("http://", "https://");
filterContext.Result = new RedirectResult(redirurl);
return;
}
}
#endif
if (!string.IsNullOrEmpty(IsRewriteToHttps) && IsRewriteToHttps == "1")
{
if (response.Filter == null) return;
if (response.ContentType == "text/html" && response.StatusCode == 200)
{
Func<string, string> todo = content =>
{
StringBuilder sb = new StringBuilder(content);
//todo regex
Regex re = new Regex(@"regex", RegexOptions.Compiled | RegexOptions.IgnoreCase);
Dictionary<string, string> replacements = new Dictionary<string, string>();
foreach (Match match in re.Matches(content))
{
if (match.Success)
{
//todo
}
}
foreach (var replacement in replacements)
{
sb = sb.Replace(replacement.Key, replacement.Value);
}
return sb.ToString();
};
response.Filter = new RewriteResponse(response.Filter, response.ContentEncoding, todo);
}
}
}
}
接下来就是实现一个类.继承Stream
就可以了.
public class RewriteResponse : Stream
{
private Stream filter;
private Encoding encoding;
private readonly MemoryStream cacheStream = new MemoryStream();
private Func<string, string> todo;
public RewriteResponse(Stream filter, Encoding encoding, Func<string, string> todo)
{
this.filter = filter;
this.encoding = encoding;
this.todo = todo;
}
public override void Write(byte[] buffer, int offset, int count)
{
cacheStream.Write(buffer, offset, count);
}
public override void Flush()
{
if (cacheStream.Length > 0 && todo != null)
{
string content = encoding.GetString(cacheStream.ToArray(), 0, (int)cacheStream.Length);
string data = todo(content);
var buffer = encoding.GetBytes(data);
this.filter.Write(buffer, 0, buffer.Length);
cacheStream.SetLength(0);
}
this.filter.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return this.filter.Seek(offset, origin);
}
public override void SetLength(long value)
{
this.filter.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
return this.filter.Read(buffer, offset, count);
}
public override bool CanRead
{
get { return this.filter.CanRead; }
}
public override bool CanSeek
{
get { return this.filter.CanSeek; }
}
public override bool CanWrite
{
get { return this.filter.CanWrite; }
}
public override long Length
{
get { return this.filter.Length; }
}
public override long Position
{
get { return this.filter.Position; }
set { this.filter.Position = value; }
}
}
至此.大部分已经完成了.最后一步就是在Global.asax
中添加我们的过滤器.如下:
public void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//其他过滤器
filters.Add(new RewriteHttpsFilterAttribute());
}
就这样.简单吧.