Helper在Razor中生成“友好URL”(C#/ MVC 4)

时间:2013-06-13 16:23:16

标签: c# asp.net-mvc-4 razor

目标

创建一些在Razor中将字符串转换为友好字符串的东西(我正在使用C#/ MVC4)

问题

我有以下代码:

<li>
   <img 
    src="~/Images/Products/@Model["CategoryName"]/@Model["ProductThumbnailUrl"]"
   />
</li>

我的类别名称如下:CDs, DVDs and Bluray我希望使用类似这样的内容将cds-dvds-and-blurays连接为“友好字符串”:

<li>
   <img 
    src="~/Images/Products
          /@HtmlHelper.ConvertToFriendlyString(@Model["CategoryName"])
          /@Model["ProductThumbnailUrl"]"
   />
</li>

你们都明白了吗?

那么,有人有任何想法吗?

提前致谢。

1 个答案:

答案 0 :(得分:5)

我以前做过这个。当我挖掘代码时,需要考虑以下事项:

  1. 确保存储生成的网址,以便进行碰撞检测;将字符串转换为友好的URL几乎肯定是有损的,因此您需要逻辑来解决冲突的名称。
  2. 您应该尝试将变音符号转换为更容易打字的字符。
  3. 考虑将url-to-resource映射设为1:多关系;如果您的资源名称发生更改,您可能需要生成新的网址将旧网址重定向到新网址。
  4. 更新:这是我的代码。 Stack Overflow方法没问题,但我更喜欢我的方法;而不是使用一组字符替换,它使用伟大的.NET Unicode库来创建更友好的字符:

    public static string ConvertToFriendlyUrl(string text)
    {
        var decomposed = text.Normalize(NormalizationForm.FormKD);
        var builder = new StringBuilder();
        foreach (var ch in decomposed)
        {
            var charInfo = CharUnicodeInfo.GetUnicodeCategory(ch);
            switch (charInfo)
            {
                // Keep these as they are
                case UnicodeCategory.DecimalDigitNumber:
                case UnicodeCategory.LetterNumber:
                case UnicodeCategory.LowercaseLetter:
                case UnicodeCategory.CurrencySymbol:
                case UnicodeCategory.OtherLetter:
                case UnicodeCategory.OtherNumber:
                    builder.Append(ch);
                    break;
    
                // Convert these to dashes
                case UnicodeCategory.DashPunctuation:
                case UnicodeCategory.MathSymbol:
                case UnicodeCategory.ModifierSymbol:
                case UnicodeCategory.OtherPunctuation:
                case UnicodeCategory.OtherSymbol:
                case UnicodeCategory.SpaceSeparator:
                    builder.Append('-');
                    break;
    
                // Convert to lower-case
                case UnicodeCategory.TitlecaseLetter:
                case UnicodeCategory.UppercaseLetter:
                    builder.Append(char.ToLowerInvariant(ch));
                    break;
    
                // Ignore certain types of characters
                case UnicodeCategory.OpenPunctuation:
                case UnicodeCategory.ClosePunctuation:
                case UnicodeCategory.ConnectorPunctuation:
                case UnicodeCategory.Control:
                case UnicodeCategory.EnclosingMark:
                case UnicodeCategory.FinalQuotePunctuation:
                case UnicodeCategory.Format:
                case UnicodeCategory.InitialQuotePunctuation:
                case UnicodeCategory.LineSeparator:
                case UnicodeCategory.ModifierLetter:
                case UnicodeCategory.NonSpacingMark:
                case UnicodeCategory.OtherNotAssigned:
                case UnicodeCategory.ParagraphSeparator:
                case UnicodeCategory.PrivateUse:
                case UnicodeCategory.SpacingCombiningMark:
                case UnicodeCategory.Surrogate:
                    break;
            }
        }
    
        var built = builder.ToString();
        while (built.Contains("--")) 
            built = built.Replace("--", "-");
        while (built.EndsWith("-"))
        {
            built = built.Substring(0, built.Length - 1);
        }
        while (built.StartsWith("-"))
        {
            built = built.Substring(1, built.Length - 1);
        }
        return built;
    }
    
    public static string GetIncrementedUrl(string url)
    {
        var parts = url.Split('-');
        var lastPortion = parts.LastOrDefault();
        int numToInc;
        bool incExisting;
        if (lastPortion == null)
        {
            numToInc = 1;
            incExisting = false;
        }
        else
        {
            if (int.TryParse(lastPortion, out numToInc))
            {
                incExisting = true;
            }
            else
            {
                incExisting = false;
                numToInc = 1;
            }
        }
    
        var fragToKeep = incExisting 
            ? string.Join("-", parts.Take(parts.Length - 1).ToArray()) 
            : url;
        return fragToKeep + "-" + (numToInc + 1).ToString();
    }
    
    public static string SeekUrl(
        string name, Func<string, bool> uniquenessCheck)
    {
        var urlName = UrlUtils.ConvertToFriendlyUrl(name);
        while (!uniquenessCheck(urlName))
        {
            urlName = UrlUtils.GetIncrementedUrl(urlName);
        }
    
        return urlName;
    }