2010-12-12 120 views
3

我试图创建ActionFilter来替换HTML中的某些文本。基本上,当服务器使用SSL时,我想用引用直接将我的CDN(http://cdn.example.com)引用替换为我的服务器(https://www.example.com)。因此,结构是这样的(我假设OnResultExecuted是我应该开始):如何使用ASP.NET MVC ActionFilter替换呈现的HTML中的URL

public class CdnSslAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     if(filterContext.HttpContext.Request.IsSecureConnection) 
     { 
      // when the connection is secure, 
      // somehow replace all instances of http://cdn.example.com 
      // with https://www.example.com 
     } 
    } 
} 

这将在我的安全控制器一起使用:

[CdnSsl] 
public class SecureController : Controller 
{ 
} 

我想这样做的原因是我的CDN不支持SSL。 Master网页中有CDN资源的参考资料。例如:

<link href="http://cdn.example.com/Content/base.css" rel="stylesheet" type="text/css" /> 

回答

5

最后我用这个博客后的变化:

http://arranmaclean.wordpress.com/2010/08/10/minify-html-with-net-mvc-actionfilter/

用我自己的过滤器:

public class CdnSslAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsSecureConnection) 
     { 
      var response = filterContext.HttpContext.Response; 
      response.Filter = new CdnSslFilter(response.Filter); 
     } 
    } 
} 

然后过滤器看起来像这样(略去了一些代码):

public class CdnSslFilter : Stream 
{ 
    private Stream _shrink; 
    private Func<string, string> _filter; 

    public CdnSslFilter(Stream shrink) 
    { 
     _shrink = shrink; 
     _filter = s => Regex.Replace(s,@"http://cdn\.","https://www.", RegexOptions.IgnoreCase); 
    } 

    //overridden functions omitted for clarity. See above blog post. 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     // capture the data and convert to string 
     byte[] data = new byte[count]; 
     Buffer.BlockCopy(buffer, offset, data, 0, count); 
     string s = Encoding.Default.GetString(buffer); 

     // filter the string 
     s = _filter(s); 

     // write the data to stream 
     byte[] outdata = Encoding.Default.GetBytes(s); 
     _shrink.Write(outdata, 0, outdata.GetLength(0)); 
    } 
} 
0

我不知道,但@Haacked在这个question的答案可以帮助。

0

对动作过滤器内部生成的输出执行替换会有点复杂。

一个更简单的方法(如果您可以编辑您的母版页)将编写一个新的Html帮助器方法(类似于Html.Content()助手),将有条件地发出正确的URL。如果你想要替换只发生在某些控制器上,那么你仍然可以有一个动作过滤器,但它只会在Request.Items中设置一些标志,并且你的帮手可以检查该标志。

0

我的建议是遵循@ marcind的方法,一种可能是使用自定义扩展方法根据当前url方案生成正确的url。这种方法的

public static MvcHtmlString CdnActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName) 
{ 
    if(helper.ViewContext.HttpContext.Request.IsSecureConnection) 
    { 
     return helper.ActionLink(linkText, actionName, controllerName, "https", "www.yourhost.com"...); 
    } 
    return helper.ActionLink(linkText, actionName, controllerName); 
} 

一个缺点是,你需要替换所有当前ActionLink调用你的观点(或者至少你需要的那些)与调用该扩展方法。

+0

这一切都取决于开发人员是否正在处理源代码不是“自己”。我正在开发一个系统的插件,我不允许修改代码。这意味着我必须修改响应以更改UI的某些部分。 – 2017-05-01 13:15:04