Как заменить URL в отображаемом HTML с помощью ASP.NET MVC ActionFilter - PullRequest
3 голосов
/ 12 декабря 2010

Я пытаюсь создать ActionFilter , чтобы заменить некоторый текст в моем HTML. В основном, когда сервер использует SSL, я хочу заменить ссылки на мой CDN (http://cdn.example.com) ссылками непосредственно на мой сервер (https://www.example.com).). Итак, структура примерно такая (я предполагаю, что OnResultExecuted - это то, где я должен старт):

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. И на главных страницах есть ссылки на ресурсы CDN. Пример:

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

Ответы [ 4 ]

5 голосов
/ 13 декабря 2010

Я использовал вариант этого сообщения в блоге:

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 голосов
/ 12 декабря 2010

Выполнение замен для сгенерированного вывода внутри фильтра действий будет немного сложным.

Более простой подход (если вы можете редактировать свои главные страницы) - написать новый вспомогательный метод HTML (аналогичноHtml.Content() помощник), который будет выдавать правильный URL-адрес.Если вы хотите, чтобы эта замена происходила только для определенных контроллеров, у вас все равно мог бы быть фильтр действий, но все, что он сделал бы, это установил бы некоторый флаг в Request.Items, и ваш помощник мог бы проверить этот флаг.

0 голосов
/ 12 декабря 2010

Мое предложение состоит в том, чтобы следовать подходу @ 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 голосов
/ 12 декабря 2010

Не знаю, но ответ от @Hacked на этот вопрос может помочь.

...