2010-08-24 97 views
9

雖然Gravatar服務的API(嗯,它實際上只是一個URL)非常簡單,但是有一個簡單的輔助方法可以很好地反映所有可用的選項的Gravatar?訪問Gravatar圖像的ASP.NET MVC助手

  • 圖像尺寸
  • 默認圖像(當用戶未指定一個)
  • 評分(G/PG/R/X)

理想地,這將是一個HtmlHelper擴展方法。我正在瞄準.NET4上的MVC2,但我想其他人也會對早期版本的選項感興趣。

編輯實現應該允許爲生成的HTML元素提供額外的屬性。

回答

19

謝謝您的回答。最後我寫了自己的解決方案,所以我會在這裏發佈給其他任何可能發現它的人。

它迎合了Gravatar現在支持的所有功能,如問題中所列。

使用方法如下:

<%= Html.Gravatar(Model.User.EmailAddress) %> 

我任何,呃,選項提供可選的參數。這些可以合併。

// Use a specific image size (the default is 80px) 
Html.Gravatar(Model.User.EmailAddress, size:64) 

// Specify what image should appear if the email address is not 
// associated with a Gravatar account 
Html.Gravatar(Model.User.EmailAddress, 
       defaultImage:GravatarDefaultImage.Identicon) 

// Specify the maximum rating allowed for images 
Html.Gravatar(Model.User.EmailAddress, rating:GravatarRating.Pg) 

// Add any additional HTML attributes for the <img /> tag 
Html.Gravatar(Model.User.EmailAddress, 
       htmlAttributes:new { @class = "gravatar" }) 

下面的代碼:

using System; 
using System.Diagnostics; 
using System.Security.Cryptography; 
using System.Text; 
using System.Web.Mvc; 
using System.Web.Routing; 

namespace SampleNamespace 
{ 
    public static class HtmlHelperGravatar 
    { 
     /// <summary> 
     /// Creates HTML for an <c>img</c> element that presents a Gravatar icon. 
     /// </summary> 
     /// <param name="html">The <see cref="HtmlHelper"/> upon which this extension method is provided.</param> 
     /// <param name="email">The email address used to identify the icon.</param> 
     /// <param name="size">An optional parameter that specifies the size of the square image in pixels.</param> 
     /// <param name="rating">An optional parameter that specifies the safety level of allowed images.</param> 
     /// <param name="defaultImage">An optional parameter that controls what image is displayed for email addresses that don't have associated Gravatar icons.</param> 
     /// <param name="htmlAttributes">An optional parameter holding additional attributes to be included on the <c>img</c> element.</param> 
     /// <returns>An HTML string of the <c>img</c> element that presents a Gravatar icon.</returns> 
     public static string Gravatar(this HtmlHelper html, 
             string email, 
             int? size = null, 
             GravatarRating rating = GravatarRating.Default, 
             GravatarDefaultImage defaultImage = GravatarDefaultImage.MysteryMan, 
             object htmlAttributes = null) 
     { 
      var url = new StringBuilder("//www.gravatar.com/avatar/", 90); 
      url.Append(GetEmailHash(email)); 

      var isFirst = true; 
      Action<string,string> addParam = (p,v) => 
       { 
        url.Append(isFirst ? '?' : '&'); 
        isFirst = false; 
        url.Append(p); 
        url.Append('='); 
        url.Append(v); 
       }; 

      if (size != null) 
      { 
       if (size < 1 || size > 512) 
        throw new ArgumentOutOfRangeException("size", size, "Must be null or between 1 and 512, inclusive."); 
       addParam("s", size.Value.ToString()); 
      } 

      if (rating != GravatarRating.Default) 
       addParam("r", rating.ToString().ToLower()); 

      if (defaultImage != GravatarDefaultImage.Default) 
      { 
       if (defaultImage==GravatarDefaultImage.Http404) 
        addParam("d", "404"); 
       else if (defaultImage==GravatarDefaultImage.Identicon) 
        addParam("d", "identicon"); 
       if (defaultImage==GravatarDefaultImage.MonsterId) 
        addParam("d", "monsterid"); 
       if (defaultImage==GravatarDefaultImage.MysteryMan) 
        addParam("d", "mm"); 
       if (defaultImage==GravatarDefaultImage.Wavatar) 
        addParam("d", "wavatar"); 
      } 

      var tag = new TagBuilder("img"); 
      tag.MergeAttributes(new RouteValueDictionary(htmlAttributes)); 
      tag.Attributes.Add("src", url.ToString()); 

      if (size!=null) 
      { 
       tag.Attributes.Add("width", size.ToString()); 
       tag.Attributes.Add("height", size.ToString()); 
      } 

      return tag.ToString(); 
     } 

     private static string GetEmailHash(string email) 
     { 
      if (email == null) 
       return new string('0', 32); 

      email = email.Trim().ToLower(); 

      var emailBytes = Encoding.ASCII.GetBytes(email); 
      var hashBytes = new MD5CryptoServiceProvider().ComputeHash(emailBytes); 

      Debug.Assert(hashBytes.Length == 16); 

      var hash = new StringBuilder(); 
      foreach (var b in hashBytes) 
       hash.Append(b.ToString("x2")); 
      return hash.ToString(); 
     } 
    } 

    public enum GravatarRating 
    { 
     /// <summary> 
     /// The default value as specified by the Gravatar service. That is, no rating value is specified 
     /// with the request. At the time of authoring, the default level was <see cref="G"/>. 
     /// </summary> 
     Default, 

     /// <summary> 
     /// Suitable for display on all websites with any audience type. This is the default. 
     /// </summary> 
     G, 

     /// <summary> 
     /// May contain rude gestures, provocatively dressed individuals, the lesser swear words, or mild violence. 
     /// </summary> 
     Pg, 

     /// <summary> 
     /// May contain such things as harsh profanity, intense violence, nudity, or hard drug use. 
     /// </summary> 
     R, 

     /// <summary> 
     /// May contain hardcore sexual imagery or extremely disturbing violence. 
     /// </summary> 
     X 
    } 

    public enum GravatarDefaultImage 
    { 
     /// <summary> 
     /// The default value image. That is, the image returned when no specific default value is included 
     /// with the request. At the time of authoring, this image is the Gravatar icon. 
     /// </summary> 
     Default, 

     /// <summary> 
     /// Do not load any image if none is associated with the email hash, instead return an HTTP 404 (File Not Found) response. 
     /// </summary> 
     Http404, 

     /// <summary> 
     /// A simple, cartoon-style silhouetted outline of a person (does not vary by email hash). 
     /// </summary> 
     MysteryMan, 

     /// <summary> 
     /// A geometric pattern based on an email hash. 
     /// </summary> 
     Identicon, 

     /// <summary> 
     /// A generated 'monster' with different colors, faces, etc. 
     /// </summary> 
     MonsterId, 

     /// <summary> 
     /// Generated faces with differing features and backgrounds. 
     /// </summary> 
     Wavatar 
    } 
} 
+0

我使用你的代碼,但我不知道爲什麼它不工作。我使用@ Html.Gravatar(「some_email」,100),但它會生成純文本輸出。我的意思是,而不是生成的圖像,我看到以下文字:。怎麼了? – Laserson 2012-01-17 17:24:56

+4

@Laserson,你在使用剃刀嗎?試試這個:'@ Html.Raw(Html.Gravatar(...))'。在傳統的ASPX中,使用'<%='而不是'<%:'(如果我沒有記錯的話)。ASP.NET MVC的新版本使用'MvcHtmlString'類來表示編碼的HTML字符串。此舊版本返回一個純字符串,然後在XML中轉義該字符串,這意味着XML將呈現到頁面中。上面的代碼應該被更新以返回'MvcHtmlString'的一個實例。不幸的是,我目前沒有時間這樣做。 – 2012-01-18 01:34:28

+0

@DrewNoakes:感謝。刪除評論 – Shyju 2012-02-17 19:08:36

12

我需要這一個項目,所以我把: http://www.freshclickmedia.com/blog/2008/06/aspnet-gravatar-control-update-full-source-included/

,並把它變成這樣:

public static class GravatarHtmlHelper 
{ 
    public static Gravatar Gravatar(this HtmlHelper htmlHelper, string email) 
    { 
     return new Gravatar() {Email = email, Size = 50, MaxAllowedRating = WebControls.Gravatar.RatingType.X}; 
    } 

    public static Gravatar Gravatar(this HtmlHelper htmlHelper, string email, bool outputSiteLink) 
    { 
     return new Gravatar() { Email = email, Size = 50, MaxAllowedRating = WebControls.Gravatar.RatingType.X, OutputGravatarSiteLink = outputSiteLink }; 
    } 

    public static Gravatar Gravatar(this HtmlHelper htmlHelper, string email, short size) 
    { 
     return new Gravatar() { Email = email, Size = size, MaxAllowedRating = WebControls.Gravatar.RatingType.X }; 
    } 

    public static Gravatar Gravatar(this HtmlHelper htmlHelper, string email, short size, bool outputSiteLink) 
    { 
     return new Gravatar() { Email = email, Size = size, MaxAllowedRating = WebControls.Gravatar.RatingType.X, OutputGravatarSiteLink = outputSiteLink}; 
    } 

} 

public class Gravatar 
{ 
    public enum RatingType { G, PG, R, X } 

    private string _email; 

    // outut gravatar site link true by default: 

    // customise the link title: 

    public Gravatar() 
    { 
     OutputGravatarSiteLink = true; 
     LinkTitle = "Get your avatar"; 
    } 

    /// <summary> 
    /// The Email for the user 
    /// </summary> 

    public string Email 
    { 
     get 
     { 
      return _email; 
     } 

     set 
     { 
      _email = value.ToLower(); 
     } 
    } 

    /// <summary> 
    /// Size of Gravatar image. Must be between 1 and 512. 
    /// </summary> 
    public short Size { get; set; } 

    /// <summary> 
    /// An optional "rating" parameter may follow with a value of [ G | PG | R | X ] that determines the highest rating (inclusive) that will be returned. 
    /// </summary> 
    public RatingType MaxAllowedRating { get; set; } 

    /// <summary> 
    /// Determines whether the image is wrapped in an anchor tag linking to the Gravatar sit 
    /// </summary> 
    public bool OutputGravatarSiteLink { get; set; } 

    /// <summary> 
    /// Optional property for link title for gravatar website link 
    /// </summary> 
    public string LinkTitle { get; set; } 

    /// <summary> 
    /// An optional "default" parameter may follow that specifies the full, URL encoded URL, protocol included, of a GIF, JPEG, or PNG image that should be returned if either the requested email address has no associated gravatar, or that gravatar has a rating higher than is allowed by the "rating" parameter. 
    /// </summary> 
    public string DefaultImage { get; set; } 

    public override string ToString() 
    { 

     // if the size property has been specified, ensure it is a short, and in the range 
     // 1..512: 
     try 
     { 
      // if it's not in the allowed range, throw an exception: 
      if (Size < 1 || Size > 512) 
       throw new ArgumentOutOfRangeException(); 
     } 
     catch 
     { 
      Size = 80; 
     } 

     // default the image url: 
     string imageUrl = "http://www.gravatar.com/avatar.php?"; 

     if (!string.IsNullOrEmpty(Email)) 
     { 
      // build up image url, including MD5 hash for supplied email: 
      MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); 

      UTF8Encoding encoder = new UTF8Encoding(); 
      MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); 

      byte[] hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Email)); 

      StringBuilder sb = new StringBuilder(hashedBytes.Length * 2); 
      for (int i = 0; i < hashedBytes.Length; i++) 
      { 
       sb.Append(hashedBytes[i].ToString("X2")); 
      } 

      // output parameters: 
      imageUrl += "gravatar_id=" + sb.ToString().ToLower(); 
      imageUrl += "&rating=" + MaxAllowedRating.ToString(); 
      imageUrl += "&size=" + Size.ToString(); 
     } 

     // output default parameter if specified 
     if (!string.IsNullOrEmpty(DefaultImage)) 
     { 
      imageUrl += "&default=" + HttpUtility.UrlEncode(DefaultImage); 
     } 



     var linkBuilder = new TagBuilder("a"); 
     // if we need to output the site link: 
     if (OutputGravatarSiteLink) 
     { 
      linkBuilder.MergeAttribute("href", "http://www.gravatar.com"); 
      linkBuilder.MergeAttribute("title", LinkTitle); 
     } 

     // output required attributes/img tag: 
     var builder = new TagBuilder("img"); 
     builder.MergeAttribute("width", Size.ToString()); 
     builder.MergeAttribute("height", Size.ToString()); 
     builder.MergeAttribute("src", imageUrl); 
     builder.MergeAttribute("alt", "Gravatar"); 

     string output = builder.ToString(TagRenderMode.Normal); 
     // if we need to output the site link:) 
     if (OutputGravatarSiteLink) 
     { 
      linkBuilder.InnerHtml = builder.ToString(); 
      output = linkBuilder.ToString(TagRenderMode.Normal); 
     } 

     return output; 

    } 
} 

用法:

<%= Html.Gravatar("[email protected]", true)%> 

你必須添加的過載當你需要它們的時候到html助手。我無法做所有的工作。 ;)5分鐘不壞?

+0

謝謝你。如果只有我更耐心 - 我已經實現了我自己的解決方案(發佈爲答案)......一個評論,電子郵件地址應該在散列前修剪以保證數字匹配。自從實現寫入以來,URL格式已經稍微更新了一些,但我認爲這並不重要,因爲我確定它們是向後兼容的。 – 2010-08-24 23:42:45

4

以下鏈接Rob Conery的助手擴展將是一個好的開始。

My Favorite Helpers For ASP.NET MVC

從網站的代碼:

public static class GravatarHelper { 

    public static string Gravatar(this HtmlHelper helper, string email, int size) { 
     var result = "<img src=\"{0}\" alt=\"Gravatar\" class=\"gravatar\" />"; 
     var url = GetGravatarURL(email, size); 
     return string.Format(result, url); 
    } 

    static string GetGravatarURL(string email, int size) { 
     return (string.Format("http://www.gravatar.com/avatar/{0}?s={1}&r=PG", 
        EncryptMD5(email), size.ToString())); 
    } 

    static string GetGravatarURL(string email, int size, string defaultImagePath) { 
     return GetGravatarURL(email, size) + string.Format("&default={0}", 
        defaultImagePath); 
    } 

    static string EncryptMD5(string Value) { 
     var md5 = new MD5CryptoServiceProvider(); 
     var valueArray = System.Text.Encoding.ASCII.GetBytes(Value); 
     valueArray = md5.ComputeHash(valueArray); 
     var encrypted = ""; 
     for (var i = 0; i < valueArray.Length; i++) 
      encrypted += valueArray[i].ToString("x2").ToLower(); 
     return encrypted; 
    } 
} 

HTHS,
查爾斯

+0

謝謝Charles。這個實現有一個潛在的錯誤,那就是電子郵件地址在被散列之前需要被修剪和縮小。它也不允許添加額外的HTML元素屬性(儘管我沒有在問題中提到這一點)。歡呼起來是一個好開始。 – 2010-08-24 23:39:15

2

不幸的是,我還沒有看到你的問題提前或我會推薦你​​用我的Gravatar.NET庫我已經建立,以提供一個.NET包裝整個Gravatar API。

如果你有興趣,看看這裏:http://gravatarnet.codeplex.com/

+0

感謝您的鏈接。我會檢查出來的。 – 2010-09-11 00:40:41

0

這裏是一個.NET的核心標籤助手如果有人有興趣:

using System.Security.Cryptography; 
using System.Text; 
using Microsoft.AspNetCore.Razor.TagHelpers; 

namespace App.Web.TagHelpers 
{ 
    public class GravatarTagHelper : TagHelper 
    { 
     public string Id { get; set; } 

     public string Email { get; set; } 

     public int? Size { get; set; } 

     public string Class { get; set; } 

     public string Alt { get; set; } 

     public override void Process(TagHelperContext context, TagHelperOutput output) 
     { 
      output.TagName = "img"; 
      if (!string.IsNullOrWhiteSpace(Id)) 
      { 
       output.Attributes.SetAttribute("id", Id); 
      } 
      output.Attributes.SetAttribute("alt", Alt); 
      output.Attributes.SetAttribute("src", GenerateGravatarUrl(Email)); 
      if (!string.IsNullOrWhiteSpace(Class)) 
      { 
       output.Attributes.SetAttribute("class", GenerateGravatarUrl(Class)); 
      } 
      if (Size.HasValue) 
      { 
       output.Attributes.SetAttribute("width", Size.ToString()); 
       output.Attributes.SetAttribute("height", Size.ToString()); 
      } 
     } 

     private static string GenerateGravatarUrl(string email) 
     { 
      var md5 = MD5.Create(); 
      var encoder = new UTF8Encoding(); 
      var md5Hash = md5.ComputeHash(encoder.GetBytes(email.Trim().ToLower())); 
      var md5String = new StringBuilder(md5Hash.Length * 2); 
      foreach (var character in md5Hash) 
      { 
       md5String.Append(character.ToString("X2")); 
      } 
      return $"https://www.gravatar.com/avatar/{md5String.ToString().ToLower()}?d=mm"; 
     } 
    } 
} 

使用這裏:

https://gravatartaghelper.codeplex.com/