<script type="text/javascript"> $(function () { // var r = "12"; var productsDataSource = new kendo.data.DataSource({ transport: { read: { url: "@Url.Action("GetProducts", "Home")", dataType: "json", contentType: 'application/json; charset=utf-8', type: 'GET', data: { param1: "dfvdf", param2: "val2" } // ارسال اطلاعات اضافی و سفارشی به سرور در حین درخواست }, create: { url: "@Url.Action("PostProduct","Home")", contentType: 'application/json; charset=utf-8', type: "POST" }, update: { url:// function (product) { "@Url.Action("UpdateProduct","Home")",//, +product.Id; //}, contentType: 'application/json; charset=utf-8', type: "PUT" }, destroy: { url: function (p) { return "@Url.Action("DeleteProduct","Home")/" + p.Id; }, contentType: 'application/json; charset=utf-8', type: "DELETE" }, parameterMap: function (options) { return kendo.stringify(options); } }, schema: { parse: function (data) { return data; }, data: "Data", total: "Total", model: { id: "Id", // define the model of the data source. Required for validation and property types. fields: { "Id": { type: "number", editable: false }, //تعیین نوع فیلد برای جستجوی پویا مهم است "Name": { type: "string", validation: { required: true }, editable: true }, "Discription": { type: "string", }, "Title": { type: "string", editable: false }, "GroupName": { type: "string", }, "Link": { type: "string" } } }, batch: false, }, error: function (e) { alert(e.errorThrown.stack); }, pageSize: 5, sort: { field: "Id", dir: "desc" } }); $("#report-grid").kendoGrid({ dataSource: productsDataSource, autoBind: true, scrollable: false, pageable: true, sortable: true, columns: [ { field: "Id", title: "#" }, { field: "Name", title: "Product" } ] }); }); </script>
EF Code First #10
معرفی Blazor Hybrid
Blazor Hybrid یا همون NET MAUI Blazor App راهکار Blazor هست که HTML/CSS برای UI استفاده میشه، ولی C# .NET اش دسترسی کامل به سیستم عامل داره (بر خلاف Blazor Web Assembly که محدود به Sandbox مرورگر هست)
یا Blazor Native شما دیگه UI تون HTML/CSS نیست و برای داشتن TextBox به جای input type=text، از Entry استفاده میکنید برای مثال که پشت صحنه مپ میشه به کنترلهای Native در Android / iOS / Windows
توصیه من این هست که Blazor رو به صورت Multi Mode تنظیم کنید، به صورتی که UI رو با HTML / CSS بزنید، و هم خروجی Android بگیرید و هم iOS و Web و ویندوز
برای درک بهتر این مسئله میتونید وبینارم رو در رابطه با what's new in dotnet 6 ببینید
اضافه کردن Google analytics به یک سایت، بسیار ساده است. در آن ثبت نام میکنید؛ سپس آدرس دومین خود را وارد کرده و یک قطعه کد جاوا اسکریپتی را دریافت خواهید کرد که باید به انتهای تمام صفحات سایت خود اضافه نمائید و ... همین.
اضافه کردن این کد در ASP.NET MVC میتواند در فایل layout یا همان master page سایت انجام شود تا به صورت خودکار به تمام صفحات اعمال گردد.
مشکل!
من نمیخواهم که صفحات غیرعمومی سایت نیز دارای کدهای Google analytics باشند و بیجهت Google به اینجاها نیز سرکشی زاید کند! چکار باید کرد؟
احتمالا عنوان میکنید که باید یک if و else به همراه آرایهای از نامها و آدرسهای صفحات غیرعمومی سایت تهیه کرد و بر این اساس کدهای Google analytics را در master page درج کرد یا خیر.
بله. این روش کار میکنه ولی بهینه نیست و همچنین نگهداری آن در طول زمان مشکل است. سایت توسعه خواهد یافت، صفحات غیرعمومی بیشتر خواهند شد و ممکن است در این بین فراموش شود که کدهای مرتبط به روز شوند.
روش بهتر:
آیا میتوان در یک View مشخص کرد که فیلتر Authorize در اکشن متد متناظری که آنرا رندر کرده است بکار گرفته شده است یا خیر؟
صفحات غیرعمومی سایت در ASP.NET MVC با فیلتر Authorize محافظت میشوند. این فیلتر را میتوان به کل یک کنترلر اعمال کرد تا به تمام اکشن متدهای آن اعمال شود؛ یا فقط به یک اکشن متد خاص که Viewایی خاص را رندر میکند.
نحوه پیاده سازی تشخیص وجود فیلتر Authorize را در یک View رندر شده، در متد کمکی زیر میتوان مشاهده کرد:
@helper IncludeGoogleAnalytics(WebViewPage page) { var controller = page.ViewContext.Controller; var controllerHasAuthorizeAttribute = controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true).Any(); var currentActionName = page.ViewContext.Controller.ValueProvider.GetValue("action").RawValue.ToString(); var actionHasAuthorizeAttribute = controller.GetType().GetMethods() .Where(x => x.Name == currentActionName && x.GetCustomAttributes(typeof(AuthorizeAttribute), true).Any()) .Any(); if (!controllerHasAuthorizeAttribute && !actionHasAuthorizeAttribute) { string trackingId = ConfigurationManager.AppSettings["GoogleAnalyticsID"]; <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', '@trackingId']); _gaq.push(['_trackPageview']); (function () { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> }
توضیحات:
این متد در فایلی به نام HtmlUtils قرار گرفته در پوشه app_code تعریف شده است و بکارگیری آن در یک فایل master page به نحو زیر خواهد بود:
@HtmlUtils.IncludeGoogleAnalytics(this)
در این متد به کمک خاصیت page.ViewContext.Controller میتوان به کنترلری که در حال رندر کردن View جاری است دسترسی یافت. اکنون که به کنترلر دسترسی داریم، به کمک Reflection، ویژگیها یا Attributes آنرا یافته و بررسی میکنیم که آیا دارای AuthorizeAttribute است یا خیر. بر این اساس میتوان تصمیم گرفت که آیا View در حال نمایش عمومی است یا خصوصی. اگر عمومی بود، کدهای اسکریپتی Google analytics به صورت خودکار به صفحه تزریق میشوند.
همچنین در اینجا فرض بر این است که Id منتسب به دومین جاری در کلیدی به نام GoogleAnalyticsID در فایل کانفیگ برنامه در قسمت app settings آن تعریف شده است.
رسم نمودار توسط Kendo Chart
<div id="chart"></div> <script> $("#chart").kendoChart({ series: [{ data: [1, 2, 3] }], valueAxis: { notes: { label: { rotation: 90 }, data: [{ value: 1 }] } } }); </script>
var row = new string[3]; row[0] = "Liverpool"; row[0] = "15";
public class Performance { public string TeamName { get; set; } public int Score { get; set; } }
مدل EAV چیست؟
EAV مخفف ( Entity Attribute Value ) میباشد، مدلی از طراحی دیتابیس که کاربر را به آیتمهای ثابت محدود نمیکند، فرض کنید در یک فروشگاه میخواهید چندین کالا بفروشید هر کالا هم برای خودش ویژگیهای منحصر به فرد دارد، آیا با ویژگیهای ثابت برای کالاهای متفاوت میتوان پاسخگوی نیاز مشتری بود؟ یقینا پاسخ منفی خواهد بود.
موجودیت ( Entity ): در یک سیستم میتواند کالا، مشتری، فروشنده و... باشد.ویژگی ( Attribute ):برای کالا: رنگ، وزن و... برای مشتری:نام، تلفن،آدرس و... میباشد
مقدار( value ) : هر ویژگی برابر مقداری میباشد مثلا برای رنگها آبی، قرمز و.. میباشد
جداول پایه طراحی شده:
ورود داده ها:
شیوه ورود دادهها را برای موجودیت کالا بیان میکنیم
ابتدا کالا در جدول موجودیت ثبت میگردد
سپس عنوان ویژگیهای آن مانند رنگ، وزن و... در جدول ویژگیها ثبت میگردد.
مقدار هر ویژگی هم در جدول مقدارها ثبت میشود.
در زیر شیوه ذخیره به صورت شکل مشاهده میکنید.
شیوه خواندن داده ها:
این قسمت هم به راحتی با 2 inner join میتوان به کالا، ویژگیها و مقادیر آن دست پیدا کرد.
نکات:
نکته1: این 3 جدول را باید برای هر موجودیت قابل توسعه ایجاد کرد، مثلا برای کالا، مشتری و...
نکته2: میتوان برای گروه بندی کالاها و همچنین ویژگیها جداول جداگانه ایی تعریف کرد.
نکته3: از مهمترین ویژگیهای این تفکر قابل گسترش بودن سیستم میباشد.
نکته4: میتوان برای آیتم هایی مثل نمایش داده شود یا خیر، چیدمان نمایش و...آیتم هایی به جدول ویژگیها اضافه کرد.
نکته5: این مدل در نرم افزار magento استفاده شده است.
همچنین جهت مطالعه بیشتر ساختار دیتابیس مجنتو در لینک زیر میباشد.
MAGENTO_v1.0.19700---Database-Diagram.zip
منابع: Entity–attribute–value model
در فایل ProductController.ts کدهای زیر را کپی نمایید:
module Product { export interface Scope { message: string; } export class Controller { constructor($scope: Scope) { $scope.message = "Hello from Masoud"; } } }
ابتدا یک ماژول به نام Product ایجاد میکنیم. سپس یک اینترفیس برای پیاده سازی آبجکت Scope که جهت مقید سازی عناصر DOM به آبجکتهای کنترلر مورد استفاده قرار میگیرد، ایجاد میکنیم. در داخل این اینترفیس متغیری به نام message از نوع string داریم. قصد داریم این متغیر را به یک عنصر مقید کنیم. حال یک کلاس به نام کنترلر ایجاد میکنیم که در تابع سازنده آن تزریق وابستگی برای scope$ از نوع اینترفیس Scope تعیین شده است. در نتیجه در بدنه سازنده میتوانیم به متغیر message مقدار مورد نظر را نسبت دهیم .
کلمه کلیدی
export برای تعریف عمومی کلاس استفاده شده است .
یک View ایجاد و کدهای
زیر را در آن کپی کنید :
<script type="text/javascript" src="~/scripts/app/ProductController.js"></script> <div ng-app> <div ng-controller="Product.Controller"> <p>{{message}}</p> </div> </div>
اولین نکته در تگ script است که فراخوانی فایل TypeScript باید با پسوند js. انجام گیرد. به دلیل اینکه فایلهای TypeScript بعد از کامپایل تبدیل به فایلهای JavaScript خواهند شد؛ در نتیجه پسوند آن نیز js. است. دومین نکته در فراخوانی کنترلر مورد نظر است که از ترکیب نام ماژول و نام کلاس است. بعد از اجرای پروژه خروجی به صورت زیر خواهد بود :
سپس وارد تنظیمات کتابخانه شده و روی List Workflow کلیک میکنیم :
در پنجره نامی را برای چرخه کاری انتخاب میکنیم :
درگام اول چرخه کاری ، یک Start Approval Process انتخاب میکنیم (از نوار action ریبون بالای پنجره قابل مشاهده است ؛ همچنین میتوانید چند تا از حروف این گام را تایپ کنید تا به صورت خودکار لود شود) :
سپس روی these users کلیک کرده تا تایید کننده را مشخص کنیم :
در این مرحله پنجره زیر باز شده و عنوان پیغام و محتوای آن را مینویسیم :
سپس در بخش participants نام فرد ، گروه یا افرادی که میتوانند این چرخه را تایید کنند را مشخص میکنیم :
در اینجا کاربری با نام usr1 باید بتواند این سند را تایید کند :
روی add و سپس روی OK کلیک میکنیم :
اگر در همین مرحله چرخه را publish کنیم میتوانیم آن را در لیست چرخههای کاری لیست مشاهده کنیم :
در گام بعدی نیاز به یک impersonation Step داریم (اطلاعات بیشتر درباره این گام در اینجا و اینجا ) :
سپس واژه equal که پیش فرض است و سپس عبارت سمت راست تساوی که وضعیت چرخه است :
حال میخواهیم زمانی که سند تایید شده (شرط true بود) ، عملیات تغییر دسترسی اعمال شود :
گزینه replace list item permission را انتخاب میکنیم و مانند زیر آن را تنظیم میکنیم :
سپس دسترسی جدید او :
و تایید تنظیمات اعمال شده (می توانید تغییرات را در گام تعریف شده مشاهده کنید) :
حال چرخه کاری را ذخیره و publish میکنیم:
حال اگر workflowهای کتابخانه را بررسی کنیم ، میتوانیم ذخیره شدن این چرخه را در کتابخانه ببینیم :
فقط نکته ای که نباید فراموش شود ، نحوه start شدن workflow است که باید ان را نیز تنظیم کنیم :
در همان شیرپوینت دیزاینر روی چرخه کاری کلیک راست میکنیم و در تنظیمات چرخه کاری ، مانند زیر عمل میکنیم تا به محض افزودن یا اعمال تغییرات در سند ، چرخه کاری فراخوانی شود :
با نام کاربری usr2 این سند را بارگذاری میکنیم :
اگر به Task List سایت مراجعه کنیم میتوانیم آغاز شدن چرخه کاری و پیغام فرستاده شده آن را ببینیم :
حال اگر کاربر usr1 که در بالا عملیات تایید به او انتساب داده شد ، آیتم Task list خود را باز کند ، پنجره زیر را خواهد دید :
و پس از تایید او دکمه ویرایش برای usr2 (که سند را ایجاد کرده بود) غیر فعال میشود :
- نکته اینکه در صورتی که usr2 مجدد سندی را با همان نوع و نام بارگذاری کند ، سیستم به او پیغام میدهد که دسترسی برای این کار را ندارد