public class UseAmpImageAttribute : ActionFilterAttribute { private HtmlTextWriter _htmlTextWriter; private StringWriter _stringWriter; private StringBuilder _stringBuilder; private HttpWriter _output; public override void OnActionExecuting(ActionExecutingContext filterContext) { _stringBuilder = new StringBuilder(); _stringWriter = new StringWriter(_stringBuilder); _htmlTextWriter = new HtmlTextWriter(_stringWriter); _output = (HttpWriter)filterContext.RequestContext.HttpContext.Response.Output; filterContext.RequestContext.HttpContext.Response.Output = _htmlTextWriter; } public override void OnResultExecuted(ResultExecutedContext filterContext) { var response = _stringBuilder.ToString(); // Change images to Amp-specific images response = UpdateAmpImages(response); // For AMP pages, change Script content to a link. response = ReplaceWithLink("script", response); // For AMP pages, change iFrame content to a link. response = ReplaceWithLink("iframe", response); _output.Write(response); } private string ReplaceWithLink(string tag, string response) { var doc = GetHtmlDocument(response); var elements = doc.DocumentNode.Descendants(tag); foreach (var htmlNode in elements) { if (htmlNode.Attributes["data-link"] == null) continue; var dataLink = htmlNode.Attributes["data-link"].Value; var paragraph = doc.CreateElement("p"); var text = String.Format("[Embedded Link] {0}", dataLink); var anchor = doc.CreateElement("a"); anchor.InnerHtml = text; anchor.Attributes.Add("href", dataLink); anchor.Attributes.Add("title", text); paragraph.InnerHtml = anchor.OuterHtml; var original = htmlNode.OuterHtml; var replacement = paragraph.OuterHtml; response = response.Replace(original, replacement); } return response; } private string UpdateAmpImages(string response) { // Use HtmlAgilityPack (install-package HtmlAgilityPack) var doc = GetHtmlDocument(response); var imageList = doc.DocumentNode.Descendants("img"); const string ampImage = "amp-img"; if (!imageList.Any()) return response; if (!HtmlNode.ElementsFlags.ContainsKey("amp-img")) { HtmlNode.ElementsFlags.Add("amp-img", HtmlElementFlag.Closed); } foreach (var imgTag in imageList) { var original = imgTag.OuterHtml; var replacement = imgTag.Clone(); replacement.Name = ampImage; replacement.Attributes.Remove("caption"); response = response.Replace(original, replacement.OuterHtml); } return response; } private HtmlDocument GetHtmlDocument(string htmlContent) { var doc = new HtmlDocument { OptionOutputAsXml = true, OptionDefaultStreamEncoding = Encoding.UTF8 }; doc.LoadHtml(htmlContent); return doc; } }
آشنایی با فرمت OPML
OPML یا Outline Processor Markup Language اساسا فایلی است مبتنی بر XML که امروزه بیشتر جهت توزیع لینکهای تغذیه خبری سایتها (RSS/Atom و امثال آن) مورد استفاده قرار میگیرد.
به بیانی سادهتر، بجای اینکه بگویند ما به این 100 وبلاگ علاقمند هستیم و لینک تک تک آنها را به شما ارائه بدهند، یک فایل OPML استاندارد از آنها درست کرده و در اختیار شما قرار میدهند. به این صورت با چند کلیک ساده، این فایل در نرم افزار فیدخوان شما import شده و آدرسها بلافاصله قابل استفاده خواهند بود.
نمونهای از این فرمت:
<?xml version="1.0" encoding="UTF-8"?> <opml version="1.0"> <head> <title>Subscriptions in Google Reader</title> </head> <body> <outline title="Programming"> <outline text="Vahid's Blog" title="Vahid's Blog" type="atom" xmlUrl="http://feeds.feedburner.com/vahidnasiri" htmlUrl="https://www.dntips.ir/"/>
نحوه استفاده از آنها در Google reader
بعد از ورود به قسمت تنظیمات Google reader ، با استفاده از قسمت import/export میتوان یک فایل OPML را به آن معرفی کرد (شکل زیر):
و یا با استفاده از برنامه باکیفیت و رایگان FeedDemon و قسمت import feeds آن میتوان یک فایل OPML را به برنامه وارد کرد. البته اینجا امکانات بیشتری را نسبت به Google reader دراختیار شما قرار میدهد و میتوانید از لیست دریافتی، موارد مورد نظر را انتخاب کنید و نه تمامی آنها را.
اگر علاقمند بودید که این فایلها را در برنامههای دات نت خود import کنید، کتابخانه سورس باز Argotic Syndication Framework این امکان را در اختیار شما قرار میدهد.
به روز رسانی
- «از کدام فیدخوان تحت وب استفاده میکنید؟»
- «به روز رسانی فایل OPML وبلاگهای IT ایرانی؛ شهریور 94»
دانت فریم ورک با بهرهگیری از این تکنولوژیها، امکاناتی را برای ایجاد HTTP سرویسها، به ما میدهد و قبل از بکارگیری لازم است انتخاب کنیم که از کدام تکنولوژی باید استفاده کنیم.
Web Service
1. پایهی آن براساس SOAP است و دادهها را در قالب XML به ما میدهد.
2. فقط از HTTP پروتکل پشتیبانی میکند.
3. متن باز نیست اما میتوان از آن در هر کلاینتی که از XML پشتیبانی میکند، استفاده کرد.
4. فقط بر روی IIS میتوان آنرا هاست کرد.
WCF
1. پایهی پیش فرض آن براساس SOAP است و دادهها را در قالب XML به ما میدهد.
2. تکامل یافتهی وب سرویسها است (ASMX) و از پروتکلهای مختلفی همچون TCP, HTTP, HTTPS, Named Pipes, MSMQ پشتیبانی میکند.
3. مشکل اصلی WCF در بد قلقی و گسترده بودن تنظیمات آن میباشد.
4. متن باز نیست، اما میتوان از آن در هر کلاینتی که از XML پشتیبانی میکند، استفاده کرد.
5. بر روی IIS یا برنامهها و یا ویندوز سرویسها، میتوان آنرا هاست کرد.
WCF REST
1. برای استفاده از WCF و WCF REST باید حتما webHttpBindings را فعال کرده باشید.
2. از دستور العملهای HTTP Get و HTTP POST با استفاده از ترکیب خصیصههای [WebGet] و [WebInvoke] ، پشتیبانی میکند.
3. برای فعال کردن سایر دستور العملهای HTTP باید تنظیماتی را در IIS انجام دهید، تا درخواستهایی که بر اساس دستورالعملهای ویژهی در فایل svc. میباشند را قبول کند.
4. ارسال دیتا به آن از طریق پارامتر، با استفاده از WebGet احتیاج به تنظیماتی دارد و یا UriTemplate باید مشخص شود.
5. از XML, JSON and ATOM پشتیبانی میکند.
Web API
1. یک فریم ورک جدید برای ساختن HTTP سرویس، یک راه ساده و آسان.
2. متن باز است و یک راه ایده آل برای ساخت REST-ful سرویسها بر روی دات نت فریم ورک.
3. برخلاف WCF Rest، سرویسهای آن از ویژگیهای کامل HTTP مانند ( URIs, request/response headers, caching, versioning various content formats) پشتیبانی میکنند.
4. همچنین از ویژگیهای کامل MVC از قبیل routing, controllers, action results, filter, model binders, IOC container or dependency injection, unit testing بهسادگی و قوی پشتیبانی میکند.
5. بر روی IIS و یا برنامهها، میتوان آنرا هاست کرد.
6. یک معماری سبک و مناسب برای دستگاههایی که پهنای باند محدودی دارند، مانند گوشیهای هوشمند.
7. پاسخها بوسیله Web API’s MediaTypeFormatter به صورت JSON, XML فرمت میشوند؛ و یا هر فرمتی را که شما میخواهید، بهعنوان MediaTypeFormatter اضافه کنید .
انتخاب بین WCF یا WEB API
1.انتخاب WCF زمانی مناسب است که شما میخواهید یک سرویس را ایجاد کنید که باید از سناریوهای مختلفی از قبیل پیغامهای یکطرفه و صف پیغامها و ارتباطات دو طرفه پشتیبانی کند و یا میخواهید یک سرویس را ایجاد کنید که از کانالهای انتقال سریع استفاده کند؛ از قبیل TCP و Named Pipes و یا شاید گاهی UDP در WCF 4.5 و همچنین میخواهید از HTTP پشتیبانی کند؛ وقتی که همهی کانالهای دیگر انتقال در دسترس نیستند.
2. انتخاب Web API زمانی مناسب است که شما میخواهید یک resource-oriented سرویس را بر روی HTTP ایجاد کنید. در اینجا میتوان از ویژگیهای کامل HTTP مانند URIs, request/response headers, caching, versioning, various content formats استفاده کرد و یا میخواهید سرویس را در معرض طیف گستردهای از کلاینتها شامل مرورگرها، موبایلها، iphone و تبلت قرار دهید.
- بر روی پایگاه داده مورد نظر راست کلیک کرده و از گزینه Tasks گزینه Copy Database را انتخاب کنید.
- پس از ظاهر شدن پنجره کپی گزینه Next را انتخاب و در مرحله مبدا و مقصد، سرور جاری را انتخاب کنید و به مرحله بعد بروید.
این برای زمانی است که شما میخواهید پایگاه داده را در سرور دیگری کپی نماید - در پنجره Transfer Method دو روش Detach and Attach و استفاده از SQL Management Object وجود دارد که با همان روش اول به مرحله بعد بروید
- در مرحله بعد نام پایگاه داده شما انتخاب شده به مرحله بعد بروید.
- مرحله بعد پیکریندی پایگاه داده مقصد میباشد که نام و مسیر پایگاه داده جدید را میتوانید مشخص نمایید.
- این عملیات با SQL Server Agent صورت میپذیرد به همین خاطر Agent میبایست نصب و Start شده باشد.
- با انتخاب گزینه Next مراحل بعد را رد کرده تا عملیات آغاز شود.
- در مرحله آخر پایگاه داده قبلی را حذف نمایید.
ثبت و نگهداری تاریخ خورشیدی در SQL Server از دیرباز یکی از نگرانیهای برنامهنویسان و
طراحان پایگاه دادهها بوده است. در این نوشتار، راهکار تعریف یک DataType در SQL Server 2012 به روش CLR آموزش داده
خواهد شد.
در ویژوال استودیو یک پروژهی جدید از نوع SQL Server Database Project
به شکل زیر ایجاد کنید:
متن موجود در صفحهی بازشده را کاملاً حذف کرده و با کد زیر جایگزین کنید.
(در کد زیر همهی توابع لازم برای مقداردهی به سال، ماه، روز، ساعت، دقیقه و ثانیه و البته گرفتن مقدار از آنها، تبدیل تاریخ خورشیدی به میلادی، گرفتن تاریخ به تنهایی، گرفتن زمان به تنهایی، افزایش یا کاهش زمان برپایهی یکی از متغیرهای زمان و بررسی و اعتبارسنجی انواع بخشهای زمان گنجانده شده است. در صورت پرسش یا پیشنهاد روی هر کدام در قسمت نظرات، پیام خود را بنویسید.)
using System; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; [Serializable()] [SqlUserDefinedType(Format.Native)] public struct JalaliDate : INullable { private Int16 m_Year; private byte m_Month; private byte m_Day; private byte m_Hour; private byte m_Minute; private byte m_Second; private bool is_Null; public Int16 Year { get { return (this.m_Year); } set { m_Year = value; } } public byte Month { get { return (this.m_Month); } set { m_Month = value; } } public byte Day { get { return (this.m_Day); } set { m_Day = value; } } public byte Hour { get { return (this.m_Hour); } set { m_Hour = value; } } public byte Minute { get { return (this.m_Minute); } set { m_Minute = value; } } public byte Second { get { return (this.m_Second); } set { m_Second = value; } } public bool IsNull { get { return is_Null; } } public static JalaliDate Null { get { JalaliDate jl = new JalaliDate(); jl.is_Null = true; return (jl); } } public override string ToString() { if (this.IsNull) { return "NULL"; } else { return this.m_Year.ToString("D4") + "/" + this.m_Month.ToString("D2") + "/" + this.m_Day.ToString("D2") + " " + this.Hour.ToString("D2") + ":" + this.Minute.ToString("D2") + ":" + this.Second.ToString("D2"); } } public static JalaliDate Parse(SqlString s) { if (s.IsNull) { return Null; } System.Globalization.PersianCalendar pers = new System.Globalization.PersianCalendar(); string str = Convert.ToString(s); string[] JDate = str.Split(' ')[0].Split('/'); JalaliDate jl = new JalaliDate(); jl.Year = Convert.ToInt16(JDate[0]); byte MonthsInYear = (byte)pers.GetMonthsInYear(jl.Year); jl.Month = (byte.Parse(JDate[1]) <= MonthsInYear ? (byte.Parse(JDate[1]) > 0 ? byte.Parse(JDate[1]) : (byte)1) : MonthsInYear); byte DaysInMonth = (byte)pers.GetDaysInMonth(jl.Year, jl.Month); ; jl.Day = (byte.Parse(JDate[2]) <= DaysInMonth ? (byte.Parse(JDate[2]) > 0 ? byte.Parse(JDate[2]) : (byte)1) : DaysInMonth); if (str.Split(' ').Length > 1) { string[] JTime = str.Split(' ')[1].Split(':'); jl.Hour = (JTime.Length >= 1 ? (byte.Parse(JTime[0]) < 23 && byte.Parse(JTime[0]) >= (byte)0 ? byte.Parse(JTime[0]) : (byte)0) : (byte)0); jl.Minute = (JTime.Length >= 2 ? (byte.Parse(JTime[1]) < 59 && byte.Parse(JTime[1]) >= (byte)0 ? byte.Parse(JTime[1]) : (byte)0) : (byte)0); jl.Second = (JTime.Length >= 3 ? (byte.Parse(JTime[2]) < 59 && byte.Parse(JTime[2]) >= (byte)0 ? byte.Parse(JTime[2]) : (byte)0) : (byte)0); } else { jl.Hour = 0; jl.Minute = 0; jl.Second = 0; } return (jl); } public SqlString GetDate() { return this.m_Year.ToString("D4") + "/" + this.m_Month.ToString("D2") + "/" + this.m_Day.ToString("D2"); } public SqlString GetTime() { return this.Hour.ToString("D2") + ":" + this.Minute.ToString("D2") + ":" + this.Second.ToString("D2"); } public SqlDateTime ToGregorianTime() { System.Globalization.PersianCalendar pers = new System.Globalization.PersianCalendar(); return SqlDateTime.Parse(pers.ToDateTime(this.Year, this.Month, this.Day, this.Hour, this.Minute, this.Second, 0).ToString()); } public SqlString JalaliDateAdd(SqlString interval, int increment) { System.Globalization.PersianCalendar pers = new System.Globalization.PersianCalendar(); DateTime dt = pers.ToDateTime(this.Year, this.Month, this.Day, this.Hour, this.Minute, this.Second, 0); string CInterval = interval.ToString(); bool isConvert = true; switch (CInterval) { case "Year": dt = pers.AddYears(dt, increment); break; case "Month": dt = pers.AddMonths(dt, increment); break; case "Day": dt = pers.AddDays(dt, increment); break; case "Hour": dt = pers.AddHours(dt, increment); break; case "Minute": dt = pers.AddMinutes(dt, increment); break; case "Second": dt = pers.AddSeconds(dt, increment); break; default: isConvert = false; break; } if (isConvert == true) { this.Year = (Int16)pers.GetYear(dt); this.Month = (byte)pers.GetMonth(dt); this.Day = (byte)pers.GetDayOfMonth(dt); this.Hour = (byte)pers.GetHour(dt); this.Minute = (byte)pers.GetMinute(dt); this.Second = (byte)pers.GetSecond(dt); } return this.m_Year.ToString("D4") + "/" + this.m_Month.ToString("D2") + "/" + this.m_Day.ToString("D2") + " " + this.Hour.ToString("D2") + ":" + this.Minute.ToString("D2") + ":" + this.Second.ToString("D2"); } }
از منوهای بالا روی منوی Bulild و سپس گزینهی Publish prgJalaliDate کلیک کتید:
در پنجرهی بازشده روی دکمهی Edit کلیک کنید سپس تنظیمات مربوط به اتصال به پایگاه داده را انجام دهید.
روی دکمهی OK کلیک کنید و سپس در پنجرهی اولیه، روی دکمهی Publish کلیک کتید:
به همین سادگی، DataType مربوطه در SQL Server 2012 ساخته میشود. خبر خوش اینکه شما میتوانید با راستکلیک روی نام پروژه و انتخاب گزینهی Properties در قسمت Project Setting تنظیمات مربوط به نگارش SQL Server را انجام دهید. (از نگارش 2005 به بعد در VS 2012 پشتیبانی میشود.)
اکنون زمان آن رسیده است که DataType ایجادشده را در SQL Server 2012 بیازماییم. SQL Server را باز کنید و دستور زیر را در آن اجرا کتید.
USE Northwind GO CREATE TABLE dbo.TestTable ( Id int NOT NULL IDENTITY (1, 1), TestDate dbo.JalaliDate NULL ) ON [PRIMARY] GO
اکنون چند رکورد درون این جدول درج میکنیم:
Insert into TestTable (TestDate) Values ('1392/02/09'),('1392/02/09 22:40'),('1392/12/30 22:40')
این خطا به این خاطر است که CLR را در SQL Server فعال نکرده ایم. جهت فعالکردن CLR دستور زیر را اجرا کنید:
sp_configure 'clr enabled', 1 Reconfigure
Insert into TestTable (TestDate) Values ('1392/02/09'),('1392/02/09 22:40'),('1392/12/30 22:40')
اکنون زمان آن رسیده است که توسط یک پرسوجو، همهی توابعی که در سیشارپ برای این نوع داده نوشتیم، بیازماییم. پرسوجوی زیر را اجرا کنید:
Select TestDate.ToString() as JalaliDateTime, TestDate.GetDate() as JalaliDate, TestDate.GetTime() as JalaliTime, TestDate.ToGregorianTime() as GregorianTime, TestDate.JalaliDateAdd('Day',1) JalaliTomorrow, TestDate.Month as JalaliMonth from TestTable
نیازی به گفتن نیست که میتوانید به سادگی از توابع مربوط به DateTime در SQL Server بهره ببرید. برای مثال برای به دست آوردن فاصلهی میان دو روز از پرسوجوی زیر استفاده کنید:
Declare @a JalaliDate = '1392/02/07 00:00:00' Declare @b JalaliDate = '1392/02/05 00:00:00' SELECT DATEDIFF("DAY",@b.ToGregorianTime(),@a.ToGregorianTime()) AS DiffDate
شاد و پیروز باشید.
اسکیوال سرور ۲۰۱۹ نسخه نهایی ریلیز شد
15.0.2070.41 | 2019.150.2070.41 | 4517790 Servicing Update (GDR1) for SQL Server 2019 RTM | 2019-11-04 *new |
15.0.2000.5 | 2019.150.2000.5 | Microsoft SQL Server 2019 RTM RTM | 2019-11-04 |