URL 在 umbraco 中重定向,当找不到文档时,重定向到其他地方

URL redirect in umbraco, when document not found, redirect elsewhere

我需要从 CMS 中不存在的文档重定向到现有文档

我在旧 CMS 中安装了 Umbraco 和旧链接。我需要将这些旧链接重定向到 umbraco 中的新结构,但由于每个 CMS 的结构不同,我需要设置某种规则。

我的第一个想法是设置 IIS,当它 (Umbraco) returns 404 时会有另一个内部重定向(如果原始请求符合某些规则)。我认为这种方式最终会通过 URL 重写,但我无法正确设置它。

可能有数百个页面需要重定向,所以我希望这由服务器处理,而不是由应用程序本身处理性能问题。

/Config/umbracoSettings.config 中,您可以配置节点来处理所有未找到的页面

<errors>
<!--
    <error404>
        <errorPage culture="default">nodeId</errorPage>
    </error404>
-->

nodeId 只是带有模板的常规节点,因此您可以将您的逻辑放在那里。

你可以为你的错误页面设置一个文档类型,然后在模板或控制器中处理,根据请求重定向到另一个页面URL等。我经常用它来建议相关或基于请求的类似页面 URL.

好的,最后解决方案是创建自定义 HTTP 模块

public class Redirector : IHttpModule
    {
        #region --- Private Properties ---
        private static Logger logger = LogManager.GetCurrentClassLogger();
        private static ConcurrentDictionary<string, string> Dictionary = new ConcurrentDictionary<string, string>();
        #endregion


        #region --- LifeCycle ---
        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            logger.Error("RedirectModule: I have been initialized");
            FillDictionary();

            context.EndRequest += EndHandler;

        }

        public bool IsReusable
        {
            get { return true; }
        }

        private void FillDictionary()
        {
            logger.Error("Filling dictionary");
            try
            {
                var currentDir = Directory.GetCurrentDirectory();

                ResourceManager rm = new ResourceManager("Resources.resx",
                Assembly.GetExecutingAssembly());

                var text = Resources.DICTIONARY_FILE;
                var parsedText = text.Split('\n');
                foreach (var row in parsedText)
                {
                    var split = row.Split(';');
                    if (split == null || split.Length != 2)
                    {
                        continue;
                    }

                    if(!Dictionary.ContainsKey(split[0]))
                    {
                        logger.Trace($"Adding key {split[0]}");
                        Dictionary.TryAdd(split[0], split[1]);
                    }                    
                }

            }
            catch(Exception exception)
            {
                logger.Error(exception, "Unable to fill dictinary");
            }
        }

        #endregion

        #region --- Handlers ---

        private void EndHandler(object sender, EventArgs e)
        {
            logger.Trace("RedirectModule: End of reqest catched");
            try
            {

                HttpApplication application = (HttpApplication)sender;
                var code = application.Response.StatusCode;
                Exception currentException = application.Server.GetLastError();
                HttpException httpException = currentException != null ? (currentException as HttpException) : null;
                HttpContext context = application.Context;

                if (httpException != null)
                {
                    if (httpException.GetHttpCode() == 404)
                    {
                        logger.Trace($"RedirectModule: 404 catched in ending as exception, original path: {context.Request.Url}");
                        if (Dictionary.ContainsKey(context.Request.Url.ToString()))
                        {
                            context.Response.Redirect(Dictionary[context.Request.Url.ToString()]);
                            logger.Trace($"redirecting to {Dictionary[context.Request.Url.ToString()]}");
                        }
                        else
                        {
                            logger.Trace($"Dictionary contains no record for  {Dictionary[context.Request.Url.ToString()]}");
                            logger.Trace($"Current amount of keys in dictionary is: {Dictionary.Count}");
                        }
                    }
                    else
                    {
                        logger.Error("RedirectModule: Unknown catched as ending");
                    }
                }
                else if (code == 404)
                {
                    logger.Trace($"RedirectModule: 404 catched in ending with no exception, original Url: {context.Request.Url}");
                    if (Dictionary.ContainsKey(context.Request.Url.ToString()))
                    {
                        context.Response.Redirect(Dictionary[context.Request.Url.ToString()]);
                        logger.Trace($"redirecting to {Dictionary[context.Request.Url.ToString()]}");
                    }
                    else
                    {
                        logger.Trace($"Dictionary contains no record for  {Dictionary[context.Request.Url.ToString()]}");
                        logger.Trace($"Current amount of keys in dictionary is: {Dictionary.Count}");
                    }
                }
                else if(code != 200)
                {
                    logger.Trace("Some other error code catched");
                }
            }
            catch (Exception exception)
            {
                logger.Error(exception, "RedirectModule: Encountered and exception");
            }
        }

        #endregion


    }
}

它从资源文件中获取设置并重定向到请求的页面。唯一的挫折是我没有为重定向设置创建自定义设置 xml 所以每次设置更改时都需要重新编译(有人知道怎么做吗?httpmodule 的起始位置使得它很难加载任何表单文件)。

感谢罗伯特·福斯特,他为我指出了这个方向。