如何动态更改ASP.NET MVC中/ Content目录中的文件?

时间:2013-03-28 02:55:18

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

当我从/ Content Directory向用户提供javascript文件时,我想用一个值替换该文件中的string令牌,以便当用户请求给定文件时,它具有所有自定义他们期待。

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

  • 我有兴趣将此插入作为stream或in -memory文件执行。我更喜欢使用流,因为它可能更有效的内存。

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

我试过

  1. 使用路线指向控制器

  2. WCF代理网址

  3. 但它们对我来说都显得“难看”,我希望在项目中尽可能透明地插入/替换。

    有更清洁的方式吗?

2 个答案:

答案 0 :(得分: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是您请求的文件的名称。

不要担心网址,您可以根据需要创建另一条路线来自定义

答案 1 :(得分:1)

以下是我上面发布的答案的替代答案,考虑到您对动态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>

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