简体   繁体   English

如何使用Razor语法获取ASP.NET MVC 4中文本中URL的链接?

[英]How to get links to URLs in text in ASP.NET MVC 4 with Razor syntax?

I have a model with a text field. 我有一个带有文本字段的模型。 The text can contain several URLs. 该文本可以包含多个URL。 It does not have to contain URLs and it does not have a specific format. 它不必包含URL,也没有特定的格式。

Using 运用

@Html.DisplayFor(model => model.TextWithSomeUrls)

the text and the URLs are displayed like normal text of course. 当然,文本和URL显示为普通文本。 I would like to get the URLs displayed as working individual links though. 我想将URL显示为工作单个链接。 Is there a helper method for this in ASP.NET / Razor? 在ASP.NET / Razor中是否有一个帮助方法?

Edit : Right now the output is: 编辑 :现在输出是:

http://www.google.com, foo: bar;  http://www.yahoo.com

Which is exactly the content of the text field. 这正是文本字段的内容。

But I want to get the URLs and only the URLs rendered as links like this: 但我想获取URL,并且只将URL呈现为如下链接:

<a href="http://www.google.com">http://www.google.com</a>, foo: bar; <a href="http://www.yahoo.com">http://www.yahoo.com</a>

My solution : 我的解决方案

public static partial class HtmlExtensions
{
    private const string urlRegEx = @"((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)";

    public static MvcHtmlString DisplayWithLinksFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        string content = GetContent<TModel, TProperty>(htmlHelper, expression);
        string result = ReplaceUrlsWithLinks(content);
        return MvcHtmlString.Create(result);
    }

    private static string ReplaceUrlsWithLinks(string input)
    {
        Regex rx = new Regex(urlRegEx);
        string result = rx.Replace(input, delegate(Match match)
        {
            string url = match.ToString();
            return String.Format("<a href=\"{0}\">{0}</a>", url);
        });
        return result;
    }

    private static string GetContent<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        Func<TModel, TProperty> func = expression.Compile();
        return func(htmlHelper.ViewData.Model).ToString();
    }
}

This extension can now be used in views: 此扩展现在可以在视图中使用:

@Html.DisplayWithLinksFor(model => model.FooBar)

I had some issues with the solution: 我在解决方案上遇到了一些问题:

  1. It did not work for hostnames without dots, like localhost or any other LAN-URL 它不适用于没有点的主机名,例如localhost或任何其他LAN-URL
  2. It did not work for URLs with spaces (minor issue) 它不适用于带空格的URL(小问题)
  3. It did not encode all the rest of my data. 它没有编码我的所有其余数据。 So if there is "< !--" in the database, the page would become truncated. 因此,如果数据库中存在“<! - ”,则页面将被截断。
  4. The URI is not escaped URI未被转义

I used the code from above, extended it a bit and ended up with this: 我使用了上面的代码,扩展了一点,最后得到了这个:

private static readonly Regex urlRegEx = new Regex(@"(?<!="")((http|ftp|https|file):\/\/[\d\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)");
private static readonly Regex quotedUrlRegEx = new Regex(@"(?<!=)([""']|&quot;|&#39;)((http|ftp|https|file):\/\/[\d\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&amp;:/~\+# ])*)\1");

public static MvcHtmlString DisplayWithLinksFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    string templateName = null)
{
    var encodedHTML = htmlHelper.DisplayFor(expression, templateName);
    return MvcHtmlString.Create(ReplaceUrlsWithLinks(encodedHTML.ToHtmlString()));
}
private static string ReplaceUrlsWithLinks(string input)
{
    input = input.Replace(@"\\", @"file://").Replace('\\', '/');
    var result = quotedUrlRegEx.Replace(input, delegate(Match match)
    {
        string url = match.Groups[2].Value;
        return String.Format("<a href=\"{0}\">{1}</a>", Uri.EscapeUriString(url), ShortenURL(url));
    });
    return urlRegEx.Replace(result, delegate(Match match)
    {
        string url = match.ToString();
        return String.Format("<a href=\"{0}\">{1}</a>", Uri.EscapeUriString(url), ShortenURL(url));
    });
}
private static string ShortenURL(string url)
{
    url = url.Substring(url.IndexOf("//", StringComparison.Ordinal) + 2);
    if (url.Length < 60)
        return url;
    var host = url.Substring(0, url.IndexOf("/", StringComparison.Ordinal));
    return host + "/&hellip;";
}

Obviously not 100% tested for all URL schemes, but seems to work alright. 显然没有100%测试所有的URL方案,但似乎工作正常。

Example Input: 示例输入:

"\\02lanpc\abc\def\Bugs in the database.docx"
http://localhost:81/applications/2/?releaseNumber=1.1&buildNumber=2

Output: 输出:

<a href="file://02lanpc/abc/def/Bugs%20in%20the%20database.docx">02lanpc/abc/def/Bugs in the database.docx</a>

<a href="http://localhost:81/applications/2/?releaseNumber=1.1&amp;buildNumber=2">localhost:81/&hellip;</a>

没有这样的帮助器,但您可以创建自己的自定义助手为DisplayFor助手创建模板 ,其中包含您需要的逻辑。

Try to write your own Html Helper, like the following. 尝试编写自己的Html Helper,如下所示。

public static string Urls(this HtmlHelper helper, string value)
{  
    var items = value.Split(';'); // use your delimiter
    var sb = new StringBuilder();
    foreach(var i in items)
    {
        if(IsUrl(i)) // write a static method that checks if the value is a valid url
            sb.Append("<a href=\"" + i + "\">" + i + "</a>,");
        else
            sb.Append(i + ",");
    }
    return sb.ToString();
}

And use like that 并使用那样的

@Html.Urls(myValue)

如果文本包含mvc URL,则可以使用@Html.Action(actionName)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM