巧用asp.net 过滤所有的Response请求并替换部分内容,彻底解决MVC虚拟路径问题. 如题: 我的项目需要用到mvc,但是用习惯了asp.net的aspx文件形式,用mvc还真有点不习惯, 首当其冲的就是路径问题... 众所周知, mvc最大的特点就是重用,重用页面.重用控制器.. 但是比较郁闷的是,页面中的文件引用,图片路径问题真是无法解决. 用/代表的是网站的根目录.. 注意是浏览器的urlwww.***.com/中的这第一个/ 用./和../代表的是相对路径.但是这路径也是相对浏览器的url来指定的, 比如 www.***.com/Home/Index指向Index.aspx, 其中写了一句话
<img src="./images/a.gif" alt="" />
如果Index.aspx被另外一个 www.***.com/Home/User/Index 路径引用 则 这个图片将失效.因为只要是在客户端的路径都是相对浏览器url的. 所以我们的Index.aspx将不可重用.. 但是折中的方法就是把Index.aspx中的这句话改成
<img src="/images/a.gif" alt="" />
这样做重用问题算是解决了,可是还有一个致命的虚拟目录问题.. 如果把你的网站移植到一个子目录下.则整个程序将全部是错误..
所以最好的方法就是把路径全部相对于你的项目..从你的项目根目录开始算起..这样可移植性就高很多.
但是,浏览器根本不知道你的项目根目录是那一层.. 我们知道asp.net提供了从根目录开始的方法, ~/ ~/指向的就是当前项目的根目录.. 不过比较悲剧这个~/只只能在服务器端用.. 客户端根本不认识~/ 所以就有了下文.. 我在服务器端,把所有的输出都过滤一遍,如果输出的文本中包含 ~/ 就把 ~/ 替换成 项目在网站中的从根目录 / 开始的绝对路径 所以以后的写法就是 <img src="~/images/a.gif" alt="" /> 以后你的项目就随便移植和重用吧..哈哈.. 当然别忘啦所有的路径都从 ~/ 开始哦 - using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- using System.Web;
-
- namespace HttpModules
- {
-
- public class ResponseFilter : IHttpModule
- {
- private string vriualRootPath;
- void IHttpModule.Dispose() { }
-
-
- void IHttpModule.Init(HttpApplication context)
- {
- context.BeginRequest += (sender, e) =>
- {
- var f = new RootPathReplaceStream(context.Response.Filter);
- context.Response.Filter = f;
- };
- }
- }
-
- public class RootPathReplaceStream : Stream
- {
-
- private Stream output;
- public RootPathReplaceStream(Stream s)
- {
- output = s;
- }
- public override bool CanRead
- {
- get { return output.CanRead; }
- }
-
- public override bool CanSeek
- {
- get { return output.CanSeek; }
- }
-
- public override bool CanWrite
- {
- get { return output.CanWrite; }
- }
-
- public override void Flush()
- {
- output.Flush();
- }
-
- public override long Length
- {
- get { return output.Length; }
- }
-
- public override long Position
- {
- get { return output.Position; }
- set { output.Position = value; }
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- return output.Read(buffer, offset, count);
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- return output.Seek(offset, origin);
- }
-
- public override void SetLength(long value)
- {
- output.SetLength(value);
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- StringComparison ignore = StringComparison.CurrentCultureIgnoreCase;
- if (HttpContext.Current != null)
- {
- HttpContext context = HttpContext.Current;
- if (context.Response.ContentType.Equals("text/html", ignore))
- {
- Encoding encoding = context.Response.ContentEncoding;
-
-
- string html = encoding.GetString(buffer, offset, count);
-
-
-
-
-
-
-
-
-
- html = html.Replace("\"~/", "\"" + VriualRootPath);
-
- html = html.Replace("'~/", "'" + VriualRootPath);
-
- byte[] bytes = encoding.GetBytes(html);
- output.Write(bytes, 0, bytes.Length);
- }
- else
- {
- output.Write(buffer, offset, count);
- }
- }
- }
-
- public static string _VriualRootPath;
-
- public string VriualRootPath
- {
- get
- {
- if (_VriualRootPath == null)
- {
-
- string absRootPath = HttpContext.Current.Server.MapPath("/");
- _VriualRootPath = HttpContext.Current.Server.MapPath("~/");
-
- _VriualRootPath = VriualRootPath.Replace(absRootPath, "/");
- _VriualRootPath = VriualRootPath.Replace("\\", "/");
- }
- return _VriualRootPath;
- }
- set {
- _VriualRootPath = value;
- }
- }
- }
-
- }
|