متدهای کمکی مفید در پروژه های asp.net mvc
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: دو دقیقه

ابتدا در پروژه‌ی mvc خود یک پوشه با نامی دلخواه (مثلا MyHelpers) بسازید و سپس کلاسی با محتویات زیر را به آن اضافه کنید(نام کلاس به دلخواه Helpers گذاشته شده است) : 
public static class Helpers
{
       //در اینجا متدها ی کمکی قرار میگیرند
}
1- تبدیل تاریخ میلادی به شمسی با استفاده از کتابخانه ی Persia :
public static MvcHtmlString FarsiDate(this HtmlHelper html, DateTime dateTime)
        {
            var tag = new TagBuilder("span");
            tag.MergeAttribute("dir", "ltr");
            tag.AddCssClass("farsi-date");
            tag.SetInnerText(Calendar.ConvertToPersian(dateTime).ToString("W"));
            return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
        }
مثال استفاده : 
@Html.FarsiDate(news.DateTimeCreated)
2- زمان فارسی : 
public static MvcHtmlString FarsiTime(this HtmlHelper html, DateTime dateTime)
        {
            var tag = new TagBuilder("span");
            tag.MergeAttribute("dir", "ltr");
            tag.AddCssClass("farsi-time");
            tag.SetInnerText(Calendar.ConvertToPersian(dateTime).ToString("R"));
            return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
        }
مثال استفاده : 
@Html.FarsiTime(news.DateTimeCreated)
3- تاریخ و زمان فارسی : 
public static MvcHtmlString FarsiDateAndTime(this HtmlHelper html, DateTime dateTime)
        {
            return MvcHtmlString.Create(FarsiTime(html, dateTime).ToHtmlString() + "  ,  " + FarsiDate(html, dateTime).ToHtmlString());
        }
مثال استفاده : 
@Html.FarsiDateAndTime(news.DateTimeCreated)
4- زمان گذشته : 
public static MvcHtmlString FarsiRemaining(this HtmlHelper html, DateTime dateTime)
        {
            var tag = new TagBuilder("span");
            tag.MergeAttribute("dir", "rtl");
            tag.AddCssClass("farsi-remaining");
            tag.SetInnerText(Calendar.ConvertToPersian(dateTime).ToRelativeDateString("TY"));
            return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
        }
مثال استفاده : 
@Html.FarsiRemaining(news.DateTimeCreated)
 
5- خلاصه‌ی مطلب با استفاده از کتابخانه ی Html Agility Pack   (تعداد کلمات از کلمه‌ی اول یک متن به اندازه‌ی max )
public static string GetSummary(this HtmlHelper html, string text, int max)
        {
            string summaryHtml = string.Empty;
            // load our html document
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(text);
            int wordCount = 0;
            foreach (var element in htmlDoc.DocumentNode.ChildNodes)
            {
                // inner text will strip out all html, and give us plain text
                string elementText = element.InnerText;

                // we split by space to get all the words in this element
                string[] elementWords = elementText.Split(new char[] { ' ' });

                // and if we haven't used too many words ...
                if (wordCount <= max)
                {
                    // add the *outer* HTML (which will have proper 
                    // html formatting for this fragment) to the summary
                    summaryHtml += element.OuterHtml;
                    wordCount += elementWords.Count() + 1;
                }
                else
                {
                    break;
                }
            }
            return summaryHtml;
        }
مثال استفاده : 
@Html.Raw(Html.GetSummary(news.Content, 60))
6- گرفتن لیست Validation Error‌ها در ModelState : 
        public  static List<string> GetListOfErrors(this ModelStateDictionary modelState)
        {
            var list = modelState.ToList();
            var listErrors = new List<string>();
            foreach (var keyValuePair in list)
            {
                listErrors.AddRange(keyValuePair.Value.Errors.Select(error => error.ErrorMessage));
            }
            return listErrors;
        }
مثال استفاده (در کنترلر):
var listErrors = ModelState.GetListOfErrors();
از دوستان عزیز خواهشمندم متدهای کمکی مورد استفاده در پروژه‌های خود را در قسمت نظرات قرار دهند.
  • #
    ‫۱۲ سال و ۳ ماه قبل، جمعه ۹ تیر ۱۳۹۱، ساعت ۲۱:۰۹
    ممنون. مطلب مفیدی بود. برای حالت GetSummary کاری که من انجام می‌دم، حذف تگ‌های html است و بعد بررسی کلمات آن. به این ترتیب نیازی به کتابخانه‌های جانبی برای بررسی کلمات موجود در html نخواهد بود؛ چون هدف اصلی، متن‌های واقعی در دسترس است منهای تگ‌های موجود:
    public static string RemoveAllHtmlTags(string text)
    {
        return string.IsNullOrEmpty(text) ? 
                      string.Empty : 
                      Regex.Replace(text, @"<(.|\n)*?>", string.Empty);
    }

    • #
      ‫۹ سال و ۹ ماه قبل، سه‌شنبه ۹ دی ۱۳۹۳، ساعت ۰۰:۵۲
      اما این regex کدهای ویژه حذف نمیکنه مثل &copy; یا مثلا nbsp , ...
      • #
        ‫۹ سال و ۹ ماه قبل، سه‌شنبه ۹ دی ۱۳۹۳، ساعت ۰۳:۴۴
        بنده دستی این موارد رو حذف کردم (حاصل از مشاهده در پروژه‌های مختلف) :

         public static string RemoveAllHtmlTags(this string text)
                {
                    var withoutHtml = String.IsNullOrEmpty(text) ?
                                  String.Empty :
                                  Regex.Replace(text, @"<(.|\n)*?>", String.Empty);
        
        
        
                    withoutHtml = withoutHtml.Replace("&nbsp;", " ");
                    withoutHtml = withoutHtml.Replace("&zwnj;", " ");
                    withoutHtml = withoutHtml.Replace("&quot;", " ");
                    withoutHtml = withoutHtml.Replace("amp;", "");
                    withoutHtml = withoutHtml.Replace("&laquo;", "«");
                    withoutHtml = withoutHtml.Replace("&raquo;", "»");
        
                    return withoutHtml;
                }
      • #
        ‫۸ سال و ۱ ماه قبل، یکشنبه ۷ شهریور ۱۳۹۵، ساعت ۱۸:۱۵
        و احتمالا بعد از حذف تگ ها، با گرفتن جزئی از متن ممکن است که کلمه انتهایی به درستی تقطیع نشود
        "این یک متن ت..."
        "این یک متن تست ..."
        که این تابع می‌تونه به جای SubString مفید باشه :
        public static string TruncateAtWord(this string input, int length)
        {
            if (input == null || input.Length < length)
                return input;
            int iNextSpace = input.LastIndexOf(" ", length);
            return string.Format("{0}...", input.Substring(0, (iNextSpace > 0) ? iNextSpace : length).Trim());
        }
  • #
    ‫۱۲ سال و ۳ ماه قبل، دوشنبه ۱۲ تیر ۱۳۹۱، ساعت ۰۰:۱۵
    من هم برای seo friendly کردن URL از کد زیر استفاده میکنم
    public static class StringHelpers
    {
    public static string ToSeoUrl(this string url)
    {
    // make the url lowercase
    string encodedUrl = (url ?? "").ToLower();
    
    // replace & with and
    encodedUrl = Regex.Replace(encodedUrl, @"\&+", "and");
    
    // remove characters
    encodedUrl = encodedUrl.Replace("'", "");
    
    // remove invalid characters
    encodedUrl = Regex.Replace(encodedUrl, @"[^a-z0-9-\u0600-\u06FF]", "-");
    
    // remove duplicates
    encodedUrl = Regex.Replace(encodedUrl, @"-+", "-");
    
    // trim leading & trailing characters
    encodedUrl = encodedUrl.Trim('-');
    
    return encodedUrl;
    }
    }
  • #
    ‫۱۲ سال و ۳ ماه قبل، یکشنبه ۱۸ تیر ۱۳۹۱، ساعت ۰۲:۵۷
    ببخشید این کتابخانه Html Agility Pack   که معرفی کردید آیا امکان انتخاب تمامی radio هایی که تیک خورده رو میده. در حالت عادی با دستور زیر همه رو برمیگردونه

    var radio = doc.DocumentNode.SelectNodes("//input[@class='radio']");
    اما من میخام فقط radio هایی رو برگردونه که تیک خورده. ممنون میشم راهنمایی کنید؟
    • #
      ‫۱۲ سال و ۳ ماه قبل، یکشنبه ۱۸ تیر ۱۳۹۱، ساعت ۰۳:۳۱
      بهتره این مباحث رو در انجمن یا mailing list خودش بررسی کنید.
      زمانیکه شما نودهای radio رو دارید بقیه‌اش چیزی شبیه به این خواهد بود
      string isChecked = element.GetAttributeValue("checked", "unchecked"); 

  • #
    ‫۱۲ سال و ۳ ماه قبل، دوشنبه ۲۶ تیر ۱۳۹۱، ساعت ۰۰:۴۱
    public static class HtmlHelperExtensions
        {
            private const string Nbsp = "&nbsp;";
            private const string SelectedAttribute = " selected='selected'";
     
            public static MvcHtmlString NbspIfEmpty(this HtmlHelper helper, string value)
            {
                return new MvcHtmlString(string.IsNullOrEmpty(value) ? Nbsp : value);
            }
     
            public static MvcHtmlString SelectedIfMatch(this HtmlHelper helper, object expected, object actual)
            {
                return new MvcHtmlString(Equals(expected, actual) ? SelectedAttribute : string.Empty);
            }
        }



    و یک مثال جهت استفاده

    <select>
       @foreach (var item in ViewBag.Items)
       {
          <option@Html.SelectedIfMatch((string)ViewBag.SelectedItem,
    (string)item.ItemName)>@item.ItemName</option> } </select>

  • #
    ‫۱۲ سال و ۲ ماه قبل، سه‌شنبه ۱۷ مرداد ۱۳۹۱، ساعت ۰۲:۲۴
    با تشکر از مبحث مهمی که ارائه کردید.
    در صورتی که جهت فراخوانی اطلاعات از JQuery Ajax استفاده شود، چگونه میتوان از Helper تاریخ شمسی استفاده کرد؟
    به بیان دیگر وقتی توسط Ajax اطلاعات از سمت سرور دریافت میشود، اطلاعات بازگشتی توسط متغییری مثل Result که از نوع Json است برگشت داده میشود. که در سمت کلاینت نمیتوان از (Html.FarsiDate(news.DateTimeCreated@ استفاده کرد.
    در سمت سرور هم فرض کنید از کد زیر اتفاده شود، 
    var data = context.Tabel1.Select(
                                 p =>
                                 new
                                 {
                                     p.Date1,
                                     p.Comment,
                                     p.Cost,
                                     p.UserId,
                                 }).FirstOrDefault(p.UserId == UserId);
    data.Date1 در سمت سرور قابل تغییر نیست و با خطای Readonly متوقف میشود.
    ممنون میشوم راهنمایی بفرمائید. 
    • #
      ‫۱۲ سال و ۲ ماه قبل، سه‌شنبه ۱۷ مرداد ۱۳۹۱، ساعت ۰۳:۱۹
      خروجی json در یک View یعنی متغیری از نوع جاوا اسکریپت. این متغیر به صورت مستقیم در کدهای یک htmlHelper قابل استفاده نیست (چون از نوع دات نت و سی شارپ یا وی بی است).
      در اینجا تبدیل تاریخ مدنظر را باید همان طرف کدهای کنترلر انجام داد. یا این طرف از توابع جاوا اسکریپتی تبدیل تاریخ میلادی به شمسی باید استفاده کرد. دو context مختلف را نمی‌شود در آن واحد با هم ترکیب کرد.
      البته می‌شود داخل کدهای جاوا اسکریپتی یک View از کدهای مثلا Razor استفاده کرد اما این کدها در زمان اجرا به صورت جاوا اسکریپتی پردازش و رندر می‌شوند و نه به فرمت مثلا سی شارپ. برای نمونه می‌شود در یک View داخل کدهای JavaScript موجود از Url.Action استفاده کرد. این مورد در زمان اجرا فقط تبدیل به یک رشته JavaScript می‌شود. البته این نکته برای بکارگیری Html.FarsiDateAndTime نیز صدق می‌کند و فراخوانی آن باید داخل کدهای Ajax جاوا اسکریپتی یک View باشد (و نه خارج از آن چون context دیگر JavaScript نخواهد بود). همچنین باید درنظر داشت که Html.FarsiDateAndTime در زمان رندر شدن جاوا اسکریپت موجود در یک View، تبدیل به معادل رشته‌ای آن شده و جایگزین می‌شود. یعنی در قسمت نتیجه یک عملیات Ajax قابل استفاده نخواهد بود.

      • #
        ‫۱۲ سال و ۲ ماه قبل، سه‌شنبه ۱۷ مرداد ۱۳۹۱، ساعت ۰۳:۴۴
        ممنون بابت پاسخ سریع و کامل شما.
        اگر  «تبدیل تاریخ همان طرف کدهای کنترلر» مد نظر باشد امکان دارد راهنمایی بفرمائید؟ اگر به شکل کدهای زیر عمل کنم طبیعی است که خطا میدهد
        راه بهتری هست که قبل از Return عمل تبدیل تاریخ را انجام دهم و سپس return Json(data ,JsonRequestBehavior.AllowGet  را انجام دهم.
        ممنون
        var data = context.Tabel1.Select(
                                     p =>
                                     new
                                     {
                                         Date1= Persia.Calendar.ConvertToPersian(p.Date1),
                                         p.Comment,
                                         p.Cost,
                                         p.UserId,
                                     }).FirstOrDefault(p.UserId == UserId);
        • #
          ‫۱۲ سال و ۲ ماه قبل، سه‌شنبه ۱۷ مرداد ۱۳۹۱، ساعت ۰۳:۵۵
          چه خطایی می‌ده؟ چون من الان استفاده کردم و خطایی نداد.
          اگر یک چنین خطایی دریافت کردید:
          The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
          مربوط است به نال بودن یکی از مقادیر تاریخ ثبت شده در بانک اطلاعاتی. خاصیت را در سمت کدهای خود nullable تعریف کنید.
          • #
            ‫۱۲ سال و ۲ ماه قبل، سه‌شنبه ۱۷ مرداد ۱۳۹۱، ساعت ۰۴:۱۱
            خطای زیر را میدهد:
            LINQ to Entities does not recognize the method 'Persia.SolarDate ConvertToPersian(System.DateTime)' method, and this method cannot be translated into a store expression.  
            برای ساخت مدل
            من اول به روش دیتابیس فرست  EDMX را ساختم و سپس از ADO.NET DbContext Generator  استفاده کردم.

            • #
              ‫۱۲ سال و ۲ ماه قبل، سه‌شنبه ۱۷ مرداد ۱۳۹۱، ساعت ۰۴:۲۱
              - من برای تست از EF 4.3.1.0 استفاده کردم و به نظر این محدودیت رو حداقل با select و projection ندارد و برنامه بدون مشکل اجرا شد.
              - برای نگارش‌های قبل از آن این روش جواب می‌دهد:
               db.table.Where(...)
                       .Select(p =>
                                   new
                                   {
                                      p.Date1,
                                      p.Comment,
                                      p.Cost,
                                      p.UserId,
                                    })
                                 .AsEnumerable() // مهم
                                 .Select(...در اینجا مجاز هستید از هر نوع تابعی استفاده کنید..)
                                 .ToList();

              • #
                ‫۱۲ سال و ۲ ماه قبل، سه‌شنبه ۱۷ مرداد ۱۳۹۱، ساعت ۰۵:۰۵
                WOW Wonderful
                مثل همیشه عالی بود.
                حل شد.
    • #
      ‫۹ سال و ۱۱ ماه قبل، دوشنبه ۵ آبان ۱۳۹۳، ساعت ۱۶:۰۱
      تمام این‌ها در پشت صحنه از همین فضای نام استفاده می‌کنند. فقط کمی ساده‌ترش کردن.