در پستهای قبلی
در این پست میخواهیم با یک مثال ساده نشان دهیم که سایت ما چگونه با استفاده از OpenID Authentication می تواند از اکانت گوگل استفاده کرده و کاربر در وب سایت ما شناسایی شود.
برای اینکار ابتدا
1- کتابخانه DotNetOpenAuth را از طریق NuGet به لیست رفرنسهای پروژه وب خود اضافه نمایید
2- یک صفحه بنام Login.aspx یا هر نام دلخواهی را به پروژه خود اضافه نمایید. در نهایت کد Html صفحه شما به ید به صورت زیر باشد.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="OAuthWebTest.Login" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div id="loginform"> <div id="NotLoggedIn" runat="server"> <asp:ImageButton ID="ButtonLoginWithGoogle" runat="server" ImageUrl="Google.JPG" OnCommand="ButtonLoginWithGoogle_Click" CommandArgument="https://www.google.com/accounts/o8/id" /> <p /> <asp:Label runat="server" ID="LabelMessage" /> </div> </div> </form> </body> </html>
در کد Html بالا به خصوصیت CommandArgument از کنترل ImageButton دقت نمایید که دارای مقدار "https://www.google.com/accounts/o8/id" می باشد. در واقع این آدرس باید برای اکانت گوگل جهت احراز هویت توسط OpenID استفاده شود. (آدرس API گوگل برای استفاده از این سرویس)
3- در قسمت کد نویسی صفحه کدهای زیر را وارد نمایید.
using System; using System.Web.UI; using System.Web.UI.WebControls; using DotNetOpenAuth.OpenId.RelyingParty; namespace OAuthWebTest { public partial class Login : Page { protected void Page_Load(object sender, EventArgs e) { OpenIdRelyingParty openIdRelyingParty = new OpenIdRelyingParty(); var response = openIdRelyingParty.GetResponse(); if (response == null) return; switch (response.Status) { case AuthenticationStatus.Authenticated: NotLoggedIn.Visible = false; Session["GoogleIdentifier"] = response.ClaimedIdentifier.ToString(); Response.Redirect("Default.aspx"); break; case AuthenticationStatus.Canceled: LabelMessage.Text = "Cancelled."; break; case AuthenticationStatus.Failed: LabelMessage.Text = "Login Failed."; break; } } protected void ButtonLoginWithGoogle_Click(object src, CommandEventArgs e) { string discoveryUri = e.CommandArgument.ToString(); OpenIdRelyingParty openId = new OpenIdRelyingParty(); var returnToUrl = new UriBuilder(Request.Url) { Query = "" }; var request = openId.CreateRequest(discoveryUri, returnToUrl.Uri, returnToUrl.Uri); request.RedirectToProvider(); } } }
همانگونه که مشاهده میکنید در رویداد کلیک دکمه لوگین ButtonLoginWithGoogle_Click ابتدا آدرس یکتا گوگل (مقدار CommandArgument اختصاص داده شده به کنترل ImageButton) به همراه آدرس صفحه جاری وب سایت توسط متد CreateRequest از شی openId ترکیب شده و یک درخواست (Request) ساخته شده و در نهایت برای سرویس دهنده گوگل ارسال میشود. با اجرای پروژه با تصویر زیر روبرو میشوید بروی کلید لوگین کلیک نمایید.
در واقع با کلیک روی دکمه مورد نظر تکه کدی که در بالا شرح داده شد اجرا شده و ما را به صفحه ای شبیه تصویر پایین هدایت میکند
در صورتی که کلید Sign In انتخاب شود شما به سایت (همین برنامه) اجازه داده اید که از اطلاعات حساب کاربری شما استفاده کند. پس از کلیک به برنامه اصلی (طبق آدرس بازگشت تعیین شده در رویداد ButtonLoginWithGoogle_Click) در رویداد PageLoad صفحه لاگین اطلاعات بازگشتی از سایت سرویس دهنده (در اینجا گوگل) چک میشود و با توجه با پاسخ مورد نظر عملیاتی انجام میشود، مثلا در صورتی که شما تایید کرده باشید اطلاعات شناسایی شما توسط گوگل در کلیدی به نام GoogleIdentifier در سشن ذهیره شده و شما به صفحه اصلی سایت هدایت میشوید.
در پستهای آینده اتصال به تویتر و ف ی س بوک و سایتهای دیگر توضیح داده خواهد شد.
این روش عمومیتر است:
function addToken(data) { data.__RequestVerificationToken = $("input[name=__RequestVerificationToken]").val(); return data; }
برای
$.ajax({ // ..... data: addToken({ postId: postId }), // اضافه کردن توکن dataType: "html", // نوع داده مهم است // ..... });
که معادل قطعه کد زیر هست:
data: { "pid": pid, "__RequestVerificationToken": $('[name=__RequestVerificationToken]').val() },
البته به نظر در این حالت "dataType: "html باشد تا کار کند.
حالت سراسری آن هم تحت نظر قرار دادن رخداد مخصوص ارسالهای Ajax ای هست (نوشتن یک interceptor):
$(document).ready(function () { var securityToken = $('[name=__RequestVerificationToken]').val(); $('body').bind('ajaxSend', function (elm, xhr, s) { if (s.type == 'POST' && typeof securityToken != 'undefined') { if (s.data.length > 0) { s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken); } else { s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken); } } }); });
Apache Cordova یک فریمورک سورس باز برای ساخت اپلیکیشنهای چند سکویی موبایل (cross platform) با استفاده از Html5 میباشد.
طی چند مقاله، با استفاده کردن از این فریمورک در VS آشنا خوهیم شد.
هدف خالقان Cordova یافتن یک راه ساده برای تولید اپلیکیشنهای چند سکویی موبایل بود که برای رسیدن به این هدف تصمیم گرفتند از تکنولوژیهای بومی (native) و تکنولوژیهای وب استفاده کنند. به این نوع از اپلیکیشنهای موبایل، Hybrid Application میگویند.
Cordova دارای قابلیتهای بومی بالایی است و مهمتر اینکه به طور طبیعی توسط مرورگرها پشتیبانی میشود. بعد از تولد Corodva، این فریمورک تبدیل شده است به بهترین روش تولید اپلیکیشنهایی که بر روی چند نوع پلتفرم کار میکنند.
پیشتر محدودیتی که وجود داشت شامل این بود که اپلیکیشنهای موبایل، به چیزهایی بیشتر از HTML و مرورگرهای وب، نیاز داشتند. برخی از این نیازها عبارتند از ارتباط متقابل وب اپلیکیشنها با دوربین یا لیست شمارههای تماس گوشی که برطرف کردن آن هم به راحتی امکان پذیر نبود.
Cordova برای مقابله با این محدودیت، مجموعهای از رابطهای برنامه کاربردی را برای توسعه قابلیتهای بومی device، مانند لیست مخاطبین، دوربین، تشخیص دهندهی تغییر جهت گوشی (accelerometer) و مانند این موارد، در نظر گرفته است.
Cordova شامل یک سری کامپوننت به شرح زیر است:
- سورس کدی برای هر Container و برنامه محلی برای هر یک از سکوهای موبایل که پشتیبانی میشوند. container، کدهای Html5 را بر روی دستگاه (Device) رندر میکند. (در مطالب بعدی در مورد این مطلب توضیح خواهم داد)
- مجموعهای از رابطهای برنامهی کاربردی که امکان دسترسی به قابلیتهای بومی دستگاه را به برنامهی وبی که درون آن در حال اجرا است، میدهند.
- مجموعهای از ابزارها برای مدیریت فرآیند ایجاد پروژه، مدیریت پلاگینها، ساخت (با استفاده از SDKهای محلی) برنامههای محلی و تست برنامه بر روی دستگاه موبایل یا شبیه ساز .
برای ساخت یک برنامهی Cordova، در واقع شما یک وب اپلیکیشن میسازید و آن را داخل Container محلی، بسته بندی میکنید. سپس تست کرده و بعد از دیباگ میتوانید اپلیکیشن را توزیع کنید.
فرآیند بسته بندی :
داخل اپلیکیشن محلی، رابط کاربری اپلیکیشن شامل یک صفحهی نمایش که خود آن چیزی نیست به غیر از یک Web View که از فضای نمایش دستگاه استفاده میکند. زمانی که برنامه آغاز به کار میکند، برنامهی وب نوشته شده، درون این web view لود میشود و کنترلهای موجود، برای تعامل کاربر با برنامهی وب، در اختیار آن قرار میگیرند. مانند تعامل کاربر با محتوا، در برنامهها ی تحت وب، لینکها، کدهای نوشته شدهی js در فایلها و یا حتی میتواند به اینترنت دسترسی داشته باشد و محتوا را از یک وب سرور تغذیه کند.
درباره Web Views
Web View جزء برنامههای بومی است که برای رندر کردن محتوای وب (به عنوان نمونه صفحه HTML) درون اپلیکیشن بومی یا صفحه نمایش استفاده میشود. در اصل Web View یک Wrapper برنامه نویسی شده قابل دسترس برای نمایش محتوای صفحات وب توکار است.
به عنوان مثال:
در اندروید با استفاده از WebView موجود در (Using andoid.webkit.WebView) , در iOS با UIWebView موجود در (Using System/Library/Framworks/UIKit.framewor) به این هدف دست پیدا میکنند. وب اپلیکیشن ما درون این Container مانند سایر وب اپلیکیشنهایی است که هر روز با آنها سرو کار دارید و آنها را در مرورگر موبایل خود اجرا میکنید و میتوانید بین صفحات Navigation داشته باشید. وب اپلیکیشنهای معمول باید روی یک سرور هاست شوند. در برنامه نویسی چند سکویی با Cordova، این کار میتواند درون Cordova Application انجام گیرد.
شاید سؤالی در ذهن شما وجود داشته باشد که مرورگر معمولا به اپلیکیشنهای موجود در دستگاه، سخت افزار و یا APIهای بومی دستگاه، دسترسی ندارد. برای مثال شاید بگویید که یک وب اپلیکیشن معمولا به لیست مخاطبین با دوربین دستگاه و ... دسترسی ندارد.
جواب : در واقع امکان دسترسی به این قابلیتها توسط اپلیکیشن بومی (native mobile application) ایجاد میشود.
Cordova مجموعه ای از APIهای جاوااسکریپت را به عنوان اهرم اجازه برای دسترسی برنامه وب درون cordova container به قابلیتهای بومی دستگاه، در اختیار توسعه دهندگان قرار داده است.
این APIها در دو بخش پیاده سازی میشوند:
1-کتابخانهی جاوااسکریپت که اجازهی استفاده از قابلیتهای بومی را به وب اپلیکیشن میدهد و کد بومی مشابه در Container اجرا میشود که مربوط است به بخش بومی این API ها. در اصل یک کتابخانهی جاوا اسکریپت وجود دارد، اما بخش بومی APIها وابسته به سکوی (platform) انتخاب شده پیاده سازی میشود.
اگر شما از APIهای موجود استفاده نکنید، میتوانید آنها را از کتابخانه جاوااسکریپت و native container حذف کنید. این کار به صورت دستی شاید خوشایند نباشد ولی چون در Cordova 3.0 همهی API ها از بیرون وارد میشوند، میتوانید با استفاده از بحث مدیریت پلاگین آن، پلاگینها را اضافه یا حذف کنید. در بخشهای بعد با مثالهایی عملی این مباحث را کار خواهیم کرد.
ادامه دارد..
بازخوردهای دوره
صفحات مودال در بوت استرپ 3
با فرض اینکه شما در فراخوانی مودال اول مشکلی نداشته باشید . فرض میکنیم شما عکس رو با ajax فراخوانی کرده و در مودال دوم نمایش میدهید . فقط کافیست شما در مودال اول یک دکمه قرا دهید و با اون دکمه مودال دوم رو فراخوانی کنید . یک فایل نمونه پیوست شد.
testmodal-(2).html
من خودم اکثر اوقات با json مقادیر مورد نظر رو در مودال نشون میدم ، چیزی شبیه به این :
رویداد کلیک ردیفهای لیست داخل مودال اول :
testmodal-(2).html
من خودم اکثر اوقات با json مقادیر مورد نظر رو در مودال نشون میدم ، چیزی شبیه به این :
function gettData(code) { $.ajax({ url: '@Url.Action(MVC.X.Y())', data: { code: code }, type: "POST", success: function (data) { $("#title").html(data.Title); $("#user-image").html(data.imagePath); }, error: function (response) { } }); }
$(document).on('click', '.item', function () { getData($(this).data("code")); $("#SecondModal").modal('toggle'); });
چند روش استفاده از ng-class در anuglarjs بررسی میکند
String syntax
<div ng-class="textType">Look! I'm Words!</div>
<div ng-class="[styleOne, styleTwo]">Look! I'm Words!</div>
<div ng-class="{ 'text-success': awesome, 'text-large': giant }">
ng-class="$even ? 'even-row' : 'odd-row'">
و .......
اشتراکها
6.Visual Studio 2017 15.9 منتشر شد
These are the customer-reported issues addressed in 15.9.6:
- Installation failures of the Unity Editor component in China.
- Starting a new nanoFramework project from a template.
- Deployment errors after VS2017 update.
- Android Deploy failed - Error ADB0010.
- Error in German translation: info bar "session closed unexpectedly".
- Visual Studio 2017 create offline layout problem: Failed to load from stream for non-ENU layouts.
- Extension auto-update can leave extension disabled.
قسمت دوم
همچین کدی (در صورت فعال بودن Lazy Load در ORM) در صورتی که جدول Customers دارای 1000 رکورد باشد، باعث میشود برنامه 1001 دستور sql تولید و در بانک اجرا گردد.
ایده دیگری هم وجود دارد. شما میتوانید MiniProfiler را برای کاربر Admin یا کاربر Debugger فعال و برای بقیه غیر فعال کنید. در باب MiniProfiler مسائل زیادی وجود دارد که چند نمونه از آن در همین سایت در این مقاله و این مقاله در دسترس است. البته میتوانید از ابزارهای دیگری مانند Glimpse که در این زمینه وجود دارد نیز استفاده کنید. لب کلام این نکته استفاده از profiler برای نرم افزار خود میباشد.
8.ORM Lazy Load
در هنگام استفاده از ORMها دقت کنید کجا از Lazy Load استفاده میکنید. Lazy Load باعث میشود وقتی شما اطلاعات مرتبط را از بانک اطلاعات واکشی میکنید، این واکشی اطلاعات در چند query از بانک انجام شود. درعوض عدم استفاده از Lazy Load باعث میشود تمامی اطلاعات مورد نیاز شما در یک query از بانک اطلاعاتی دریافت شود. این موضوع یعنی سربار کمتر در شبکه، در بانک اطلاعاتی، در منابع حافظه و منابع پر ازرش cpu در سرورها. البته استفاده از include در حالت فعال بودن یا نبودن lazy هم داستان مجزایی دارد که اگر عمری باقی باشد راجع به آن مقاله ای خواهم نوشت.
به این نمونه دقت کنید:
List<Customer> customers = context.Customers.ToList(); foreach (Customer cust in context.Customers){ Console.WriteLine("Customer {0}, Account {1}", cust.Person.LastName.Trim() + ", " + cust.Person.FirstName, cust.AccountNumber); }
برای اطلاع بیشتر میتوانید به این مقاله مراجعه نمایید.
9.استفاده از MiniProfiler
سعی کنید از MiniProfiler در تمامی پروژهها استفاده کنید. البته وقتی نرم افزار را در اختیار مصرف کننده قرار میدهید، آن را غیر فعال کنید. میتوانید از متغیرهای compiler برای مجزا کردن buildهای متفاوت در برنامه خود استفاده کنید:
#if DEBUG then // فعال سازی MiniProfiler #endif
10. Data Paging در بانک اطلاعاتی
هنگامیکه از کامپوننتهای شرکتهای دیگر (Third party) استفاده میکنید، اطمینان حاصل کنید که صفحه بندی اطلاعات در بانک اطلاعاتی انجام میشود. برای نمونه کاپوننت گرید شرکت Telerik چند نوع صفحه بندی را پشتیبانی میکند. صفحه بندی سمت کاربر (توسط JavaScript)، صفحه بندی سمت سرور توسط کامپوننت و صفحه بندی مجازی. صفحه بندی سمت کاربر یعنی تمامی اطلاعات از سرور به کاربر فرستاده شده و در سمت کاربر عمل صفحه بندی انجام میشود. این یعنی واکشی تمامی اطلاعات از بانک و در مورد نرم افزارهای پرکاربر با حجم اطلاعات زیاد یعنی فاجعه. صفحه بندی سمت سرور ASP.NET هم یعنی واکشی اطلاعات از سرور بانک به سرور برنامه و سپس صفحه بندی توسط برنامه. این موضوع هم ممکن است مشکلات زیادی را ایجاد نماید چون باید حداقل تمامی رکوردها از اولین رکورد تا آخرین رکورد صفحه جاری از بانک واکشی شود که این عمل علاوه بر ایجاد سربار شبکه، سربار IO در بانک اطلاعاتی و سربار cpu در سرور ASP.NET ایجاد میکند. استفاده از صفحه بندی مجازی، شما را قادر میکند بتوانیم اطلاعات را در بانک صفحه بندی کرده و فقط صفحه مورد نظر خود را از بانک واکشی کنیم.
این حالت مجازی در اکثر componentها که توسط شرکتهای مختلف ایجاد شده وجود دارد ولی ممکن است نامهای متفاوتی داشته باشد. برای این موضوع باید به راهنمای component خریداری شده مراجعه کنید و یا به فرومها و... مراجعه نمایید.
11. بررسی تعداد کوئریهای صادر شده در یک صفحه و تعداد رکوردهای بازگشت داده شده توسط آنها
این به این معنا نیست که برای هر query یک context مجزا ایجاد کنید، منظور این است که به بهانه اینکه اطلاعات مختلفی از جداول مختلف مورد نیاز است، query خود را آن قدر پیچیده یا گسترده ننویسیم که یا process آن در بانک زمان و سربار زیادی ایجاد کند و یا حجم اطلاعات بلا استفاده ای را از بانک به سرور برنامه لود نماید. به جای این موضوع میتوانید در یک یا چند context دستورات مجزای واکشی اطلاعات صادر کنید تا تنها اطلاعات مورد نیاز خود را واکشی نمایید. البته این موضوع باعث نشود که تعداد queryها مثلا به 1000 عدد برسد! یعنی باید فیمابین queryهای پیچیده و queryهای ساده ولی با تعداد یکی را که مناسبتر با پروژه است انتخاب کنید که این موضوع با تجربه و تست حاصل میشود.