خواندنیهای 5 اردیبهشت
protected void Application_Start() { ViewEngines.Engines.Clear(); var veiwEngine = new RazorViewEngine(); veiwEngine.FileExtensions = new string[] { "cshtml" }; ViewEngines.Engines.Add(veiwEngine); .... }
همچنین یک Interface را نیز به نام IResourceManager تعریف میکنیم:
public interface IResourceManager { IStringLocalizer Localizer { get; } }
سپس دو کلاس دیگر را ایجاد کرده و آنها را از این اینترفیس مشتق میکنیم. در این اینترفیس، یک خصوصیت Localizer از نوع IStringLocalizer وجود دارد که باید در این کلاسها پیاده سازی شود. این کار را به کمک IStringLocalizerFactory انجام داده و مشخص میکنیم هر کلاس، از کدام ریسورس استفاده کند:
public class SchoolResourceManager : IResourceManager { public SchoolResourceManager (IStringLocalizerFactory factory) { Localizer = factory.Create(typeof(SchoolResource)); } public IStringLocalizer Localizer { get; } }
public class ArtSchoolResourceManager : IResourceManager { public ArtSchoolResourceManager(IStringLocalizerFactory factory) { Localizer = factory.Create(typeof(ArtSchoolResource)); } public IStringLocalizer Localizer { get; } }
سپس در فایل appsetting.json پروژه، یک کلید را تعریف میکنیم تا مشخص کند، نوع application، از نوع مدرسه هست یا از نوع هنرستان:
{ "ConnectionStrings": { "str": "..." }, "Type": "ArtSchool" }
در متد ConfigureServices در فایل startup تعیین میکنیم هنگام شروع به کار برنامه، با توجه به مقدار درون appsetting، کدام سرویس (manager) تزریق شود:
public void ConfigureServices(IServiceCollection services) { services.AddLocalization(); services.AddSingleton<SchoolResourceManager>(); services.AddSingleton<ArtSchoolResourceManager>(); services.AddSingleton<IResourceManager>(cnf => { var type = Configuration.GetSection("Type").Value; if (type == "ArtSchool") return cnf.GetServices<ArtSchoolResourceManager>().FirstOrDefault(); return cnf.GetServices<SchoolResourceManager>().FirstOrDefault(); }); }
خوب حالا با خیال راحت برنامه را توسعه میدهیم و در viewها و Controllerها از همان کلیدهای School و Student استفاده میکنیم:
: View
@inject IResourceManager ResourceManager <h2>@ResourceManager.Localizer["Student"] : </h2>
:Controller
public class TestController : Controller { private readonly IResourceManager _resourceManager; public TestController (IResourceManager resourceManager) { _resourceManager = resourceManager; } }
DNTProfiler
برای استفادهی از آن نیاز به نصب دات نت فریم ورک 4 بر روی سیستم شما است. همچنین نیاز است کتابخانهی کلاینت آنرا به پروژهی خود نیز اضافه کنید. اطلاعات بیشتر
- محل دریافت آخرین نگارش آن: https://github.com/VahidN/DNTProfiler/releases
- بستهی نیوگت EF پروژه: DNTProfiler.EntityFramework.Core
- بستهی نیوگت NH پروژه: DNTProfiler.NHibernate.Core
Gulp #2
ساخت پروژه گالپ
npm init
name: (Gulp-RTLbootstrap-fontawesome) version: (1.0.0) description: An Awesome workflow entry point: (index.js) index.html test command: test git repository: https://github.com/mmdsharifi/gulp-rtlBootstrap-fontawesome.git keywords: gulp,rtlbootstrap,persian bootstrap author: Mohammad Sharifi license: (ISC) MIT
نصب گالپ
npm install gulp --save-dev
ایجاد فایل gulpfile.js
touch gulpfile.js
نوشتن اولین تسک گالپ
var gulp = require('gulp');
gulp.task('task-name', function() { // Stuff here });
gulp.task('hello', function() { console.log('Hello Gulp !'); });
البته که تسکهایی که برای گالپ مینویسیم، کاراتر از این است؛ برای مثال:
gulp.task('task-name', function () { return gulp.src('source-files') // Get source files with gulp.src .pipe(aGulpPlugin()) // Sends it through a gulp plugin .pipe(gulp.dest('destination')) // Outputs the file in the destination folder })
مخزن پروژه در گیت هاب : https://github.com/mmdsharifi/gulp-rtlBootstrap-fontawesome
using System; using System.Collections; using System.Web.Mvc; using System.Xml.Serialization; namespace Neoox.Core.SeoTools { [XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")] public class Sitemap { private ArrayList map; public Sitemap() { map = new ArrayList(); } [XmlElement("url")] public Location[] Locations { get { Location[] items = new Location[map.Count]; map.CopyTo(items); return items; } set { if (value == null) return; Location[] items = (Location[])value; map.Clear(); foreach (Location item in items) map.Add(item); } } public int Add(Location item) { return map.Add(item); } } public class Location { public enum eChangeFrequency { always, hourly, daily, weekly, monthly, yearly, never } [XmlElement("loc")] public string Url { get; set; } [XmlElement("changefreq")] public eChangeFrequency? ChangeFrequency { get; set; } public bool ShouldSerializeChangeFrequency() { return ChangeFrequency.HasValue; } [XmlElement("lastmod")] public DateTime? LastModified { get; set; } public bool ShouldSerializeLastModified() { return LastModified.HasValue; } [XmlElement("priority")] public double? Priority { get; set; } public bool ShouldSerializePriority() { return Priority.HasValue; } } public class XmlResult : ActionResult { private object objectToSerialize; public XmlResult(object objectToSerialize) { this.objectToSerialize = objectToSerialize; } public object ObjectToSerialize { get { return this.objectToSerialize; } } public override void ExecuteResult(ControllerContext context) { if (this.objectToSerialize != null) { context.HttpContext.Response.Clear(); var xs = new System.Xml.Serialization.XmlSerializer(this.objectToSerialize.GetType()); context.HttpContext.Response.ContentType = "text/xml"; xs.Serialize(context.HttpContext.Response.Output, this.objectToSerialize); } } } }
public ActionResult Sitemap() { Sitemap sm = new Sitemap(); sm.Add(new Location() { Url = string.Format("http://www.TechnoDesign.ir/Articles/{0}/{1}", 1, "SEO-in-ASP.NET-MVC"), LastModified = DateTime.UtcNow, Priority = 0.5D }); return new XmlResult(sm); }
مطلبی را در مورد شبیه سازی ارسال ایمیل جهت بررسی خروجی واقعی یک برنامه قبلا نوشته بودم. در تکمیل این مبحث، برنامه رایگان و سورس بازی به نام Antix SMTP Server for Developers نیز وجود دارد که از آدرس زیر قابل دریافت است:
این برنامه به صورت یک پروسه پس زمینه اجرا شده و تواناییهای یک SMTP Server واقعی را شبیه سازی میکند؛ بدون اینکه ایمیلی را ارسال نماید. پس از اجرا، منتظر دریافت ایمیلهای ارسالی از طریق SMTP Client برنامهی شما شده و پس از دریافت ایمیلها، آنها را در پوشهای مشخص ذخیره میکند. همچنین توسط این برنامه میتوان عنوان ایمیلهای ارسالی را نیز مشاهده نمود (مزیت اصلی نسبت به روش قبلی معرفی شده). با دوبار کلیک بر روی ایمیلهای لیست شده، میتوان آنها را در mail client نصب شده مانند آوت لوک، مشاهده نمود. به این صورت یک برنامه نویس میتواند متن و فرمت ایمیلهای ارسالی توسط برنامه خود را پیش از بکارگیری آن در یک محیط واقعی کاری، کاملا بررسی و آزمایش نماید. بدیهی است که این برنامه حتی میتواند بر روی کامپیوتری دیگر در شبکه نیز قرار داشته باشد. همچنین با توجه به نحوهی توزیع ClickOnce این برنامه، هر بار که بسته شود، بررسی خواهد کرد که آیا نگارش جدیدتری از آن آماده شده است یا خیر (اگر نصاب ClickOnce آن را دریافت و نصب کنید).
اگر از دات نت فریم ورک استفاده میکنید، جهت استفاده از این شبیه ساز کافی است app.config و یا web.config برنامه شما به صورت زیر تنظیم شده باشد:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<mailSettings>
<smtp>
<network port="25" host="127.0.0.1"/>
</smtp>
</mailSettings>
</system.net>
</configuration>
پ.ن.
همانطور که در تصویر مشخص است این برنامه قادر به تفسیر عنوان ایمیل فارسی نیست (اولین عنوان بررسی شده فارسی است). اگر وقت کردید در این پروژه سورس باز شرکت کنید و نکته زیر را به آن اعمال نمائید (زیبایی یک کار سورس باز ...):
رمزگشایی عنوان یک ایمیل فارسی دریافت شده
Html Encoding
Hello%20world%20,%20hi
<html>encoding</html>
<html>encoding</html>
کاراکتر | عبارت معادل | توضیحات |
> | > | |
< | < | |
" | " | |
' | ' | یا ;apos& به غیر از IE |
& | & |
- متد System.Security.SecurityElement.Escape: این متد بیشتر برای اعمال این انکدینگ در XML بهکار میرود. در این متد 5 کاراکتر اشاره شده در بالا به عبارات معادل انکد میشوند. البته برای کاراکتر ' از عبارت ;apos& استفاده میشود.
- متدهای موجود در System.Net.WebUtility: متدهای HtmlEncode و HtmlDecode موجود در این کلاس عملیات انکدینگ را انجام میدهند. این کلاس از داتنت 4 اضافه شده است.
- متدهای کلاس System.Web.HttpUtility: در این کلاس از متدهای موجود در کلاس System.Web.Util.HttpEncoder استفاده میشود. در پیادهسازی پیشفرض، متدهای این کلاس از متدهای موجود در کلاس WebUtility استفاده میکنند. البته میتوان با فراهم کردن یک Encoder سفارشی و تنظیم آن در فایل کانفیگ (خاصیت encoderType در قسمت HttpRuntime) این رفتار را تغییر داد. دلیل اصلی جابجایی مکان پیادهسازی این متدها از دات نت 4 به بعد نیز به همین دلیل است. (اطلاعات بیشتر ^ و ^).
- متدهای موجود در System.Web.HttpServerUtility: متدهای HtmlEncode و HtmlDecode موجود در این کلاس مستقیما از متدهای موجود در کلاس HttpUtility استفاده میکنند. خاصیت Server موجود در HttpContext یا در کلاس Page از نوع این کلاس است.
- متدهای موجود در کلاس System.Web.Security.AntiXss.AntiXssEncoder: این کلاس از دات نت 4.5 اضافه شده است. همانطور که از نام این کلاس بر میآید، از HttpEncoder مشتق شده است که در متدهای مرتبط با html encoding تغییراتی در آن اعمال شده است. متدهای این کلاس برای امنیت بیشتر به جای استفاده از Black List از یک White List استفاده میکنند.
public static unsafe void HtmlEncode(string value, TextWriter output) { int index = IndexOfHtmlEncodingChars(value, 0); if (index == -1) { output.Write(value); return; } int cch = value.Length - index; fixed (char* str = value) { char* pch = str; while (index-- > 0) { output.Write(*pch++); } while (cch-- > 0) { char ch = *pch++; if (ch <= '>') { switch (ch) { case '<': output.Write("<"); break; case '>': output.Write(">"); break; case '"': output.Write("""); break; case '\'': output.Write("'"); break; case '&': output.Write("&"); break; default: output.Write(ch); break; } } else if (ch >= 160 && ch < 256) { // The seemingly arbitrary 160 comes from RFC output.Write("&#"); output.Write(((int)ch).ToString(NumberFormatInfo.InvariantInfo)); output.Write(';'); } else { output.Write(ch); } } } } private static unsafe int IndexOfHtmlEncodingChars(string s, int startPos) { int cch = s.Length - startPos; fixed (char* str = s) { for (char* pch = &str[startPos]; cch > 0; pch++, cch--) { char ch = *pch; if (ch <= '>') { switch (ch) { case '<': case '>': case '"': case '\'': case '&': return s.Length - cch; } } else if (ch >= 160 && ch < 256) { return s.Length - cch; } } } return -1; }
<div id="log"></div> <script type="text/javascript"> var element = document.getElementById('log'); element.innerText = '<html> encoding </html>'; console.log(element.innerHTML); </script>
<html> encoding </html>
<div id="log"> </div> <script type="text/javascript"> var element = document.getElementById('log'); element.innerHTML = "<html> encoding </html>"; console.log(element.innerText); </script>
<html> encoding </html>
String.htmlEncode = function (s) { var el = document.createElement("div"); el.innerText = s || ''; return el.innerHTML; };
console.log(String.htmlEncode("<html>")); //result: <html>
String.prototype.htmlEncode = function () { var el = document.createElement("div"); el.innerText = this.toString(); return el.innerHTML; };
console.log("<html>".htmlEncode()); //result: <html>
String.htmlDecode = function (s) { var el = document.createElement("div"); el.innerHTML = s || ''; return el.innerText; };
String.prototype.htmlDecode = function () { var el = document.createElement("div"); el.innerHTML = this.toString(); return el.innerText; };
console.log(String.htmlDecode("<html>")); console.log("<html>".htmlDecode());
String.htmlEncode = function (s) { return $('<div/>').text(value).html(); }; String.prototype.htmlEncode = function () { return $('<div/>').text(this.toString()).html(); };
String.htmlDecode = function (s) { return $('<div/>').html(s).text(); }; String.prototype.htmlDecode = function () { return $('<div/>').html(this.toString()).text(); };
var value = "a \n b";
String.htmlEncode = function (s) { var el = document.createElement("div"); var txt = document.createTextNode(s); el.appendChild(txt); return el.innerHTML; };
String.htmlDecode(String.htmlEncode(myString)) === myString;
var myString = "<HTML>"; String.htmlDecode(String.htmlEncode(myString)) === myString; // result: true // -------------------------------------------------------------------------- myString = "<اچ تی ام ال>"; String.htmlDecode(String.htmlEncode(myString)) === myString; // result: true
myString = "a \r b"; String.htmlDecode(String.htmlEncode(myString)) === myString; // result: false
console.log(escape(String.htmlDecode('\r'))); // result: %0A : it is url encode of character '\n' console.log(escape(String.htmlDecode('\n'))); // result: %0A console.log(escape(String.htmlDecode('\r\n'))); // result: %0A
var el = document.createElement('div'); el.innerText = '\r'; console.log(escape(el.innerText)); // result: %0A el.innerHTML = '\r'; console.log(escape(el.innerHTML)); // result: %0A console.log(escape('\r')); // result: %0D
String.htmlEncode = function (text) { text = text || ''; var encoded = ''; for (var i = 0; i < text.length; i++) { var c = text[i]; switch (c) { case '<': encoded += '<'; break; case '>': encoded += '>'; break; case '&': encoded += '&'; break; case '"': encoded += '"'; break; case "'": encoded += '''; break; default: // the upper limit can be removed to support more chars... var code = c.charCodeAt(); if (code >= 160 & code < 256) encoded += '&#' + code + ';'; else encoded += c; } } return encoded; };
function escapeHTML() { return this.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); } function unescapeHTML() { return this.stripTags().replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&'); }
var andExp = /&/g, htmlExp = [/(<|>|")/g, /(<|>|')/g, /(<|>|'|")/g], htmlCharMap = { '<': '<', '>': '>', "'": ''', '"': '"' }, htmlReplace = function (all, $1) { return htmlCharMap[$1]; }; $.extend({ // convert special html characters htmlspecialchars: function (string, quot) { return string.replace(andExp, '&').replace(htmlExp[quot || 0], htmlReplace); } });
$.htmlspecialchars("<div>");
this.escapeHTML = function (s) { this.str = this.s(s) .split('&').join('&') .split('<').join('<') .split('>').join('>'); return this; }; this.unescapeHTML = function (s) { this.str = this.stripTags(this.s(s)).str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); return this; };
5 دلیل برای استفاده از یک ابزار ORM
- امیدی به ادامهی آن باشد (نگن امروز به به! فردا ... خوب دیگه ... تموم شد! صرف نمیکنه، دیگه توسعه نمیدیم! خیلی از سیاستهای مایکروسافت همینطوری است. مثلا همون کاری که با LINQ to SQL کرد)
- چند هزار نفری پیرو و دنبال مباحث آن باشند (حداقل 2 تا فوروم رفع اشکال بتونید پیدا کنید)
- دو تا کتاب در موردش باشه
- 4 تا وبلاگ در موردش مطلب بنویسند.
و مسایلی از این دست.
به همین جهت یا روی EF یا NH سرمایه گذاری کنید.
به شخصه NH رو ترجیح میدم چون سورس باز است، به همین جهت مرگ برای آن معنی ندارد (این گروه نخواست ادامه بده ... گروههای دیگر هستند)، رایگان است، مجوزش اجازه استفاده در کارهای تجاری سورس بسته را میدهد. چندتا کتاب در موردش هست و ...
به EF شک دارم. نمیدونم مایکروسافت مثلا 4 سال دیگه آیا این را هم بازنشسته اعلام میکند یا نه.