【问题标题】:How can I dynamically alter the files in the /Content directory in ASP.NET MVC?如何动态更改 ASP.NET MVC 中 /Content 目录中的文件?
【发布时间】:2013-03-28 02:55:18
【问题描述】:

当我从 /Content 目录向用户提供 javascript 文件时,我想用一个值替换该文件中的 string 标记,以便当用户请求给定文件时,它具有他们期望的所有自定义.

我认为这意味着我需要以某种方式代理对 /Content 目录的请求,执行动态插入,并将文件提供给用户。

  • 我有兴趣以stream 或内存文件的形式执行此插入。我更喜欢使用流,因为它可能更有效的内存。

如何让 ASP.NET 代理此目录?

我试过了

  1. 使用路由指向控制器

  2. WCF 代理 URL

但它们对我来说都显得“丑陋”,我想让这种插入/替换在他的项目中尽可能透明。

有没有更清洁的方法?

【问题讨论】:

    标签: asp.net-mvc wcf asp.net-mvc-4 routes actionresult


    【解决方案1】:

    最简单的方法是在控制器上创建一个动作。

    public class JavascriptController : Controller
    {
        public ActionResult Load(string file)
        {
            var content = System.IO.File.ReadAllText(Server.MapPath(string.Format("~/Content/{0}", file)));
    
            //make replacements io content here
    
            return this.Content(content, "application/javascript");
        }
    }
    

    然后您可以像这样访问 javascript(假设您有默认路由):

    http://localhost:53287/Javascript/Load?file=file.js
    

    file.js 是您请求的文件的名称。

    不用担心 url,如果需要,您可以通过创建另一个路由来自定义它

    【讨论】:

    • 谢谢。如果我还想代理对供应商 (Telerik) 动态 javascript 文件的请求怎么办?那不是在较低的级别上运行吗?
    • 您可以更改从文件中读取所有文本的行以通过 http 请求文件内容。这是一个非常简单的解决方案,但开销更大(每个请求实际上会被处理两次)
    【解决方案2】:

    考虑到您对动态 javascript 的评论,这是我上面发布的答案的替代答案。

    首先,我不知道具体使用 mvc 或 wcf 的方法。我知道如何做到这一点的唯一方法是使用较低级别的 HttpModule

    看看下面的代码:

    public class JavascriptReplacementModule : IHttpModule
    {
        public class ResponseFilter : MemoryStream
        {
            private Stream outputStream = null;
    
            public ResponseFilter(Stream output)
            {
                outputStream = output;
            }
    
            public override void Flush()
            {
                base.Flush();
                this.Seek(0, SeekOrigin.Begin);
                var sr = new StreamReader(this);
    
                string contentInBuffer = sr.ReadToEnd();
    
                //Do replacements here
    
                outputStream.Write(UTF8Encoding.UTF8.GetBytes(contentInBuffer), 0, UTF8Encoding.UTF8.GetByteCount(contentInBuffer));
    
                outputStream.Flush();
            }
    
            protected override void Dispose(bool disposing)
            {
                outputStream.Dispose();
                base.Dispose(disposing);
            }
        }
    
        public void Dispose() { }
    
        public void Init(HttpApplication context)
        {
            context.PostRequestHandlerExecute += new EventHandler(context_PostRequestHandlerExecute);
        }
    
        void context_PostRequestHandlerExecute(object sender, EventArgs e)
        {
    
            var context = (HttpApplication)sender;
            if (context.Request.Url.AbsolutePath.StartsWith("/Content") && context.Request.Url.AbsolutePath.EndsWith(".js"))
            {
                HttpContext.Current.Response.Filter = new ResponseFilter(HttpContext.Current.Response.Filter);
            }
        }
    }
    

    并像这样注册模块(确保将完整类型放入 type 属性中):

    <system.webServer>
      <modules>
        <add name="JavascriptReplacementModule" type="JavascriptReplacementModule"/>
      </modules>
    </system.webServer>
    

    这允许您在输出流到达客户端之前对其进行修改

    【讨论】:

    • 谢谢!如果您想知道我将其用于与 CORS 和 AJAX POST 相关的安全解决方案:security.stackexchange.com/q/17036/396 如果您有什么想法,我很想听听您的想法:)
    猜你喜欢
    • 2011-09-14
    • 2021-04-05
    • 2018-09-04
    • 1970-01-01
    • 2018-11-26
    • 2011-04-17
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多