Records v2؛ پیشنهادی برای C# 9x
کتابخانه qart.js
Generate artistic QR code Demo
$ npm install qartjs
With React
This is a simple implementation of QArt as React Component. react-qart
With Angular.JS
There is a directive available for using qart.js in Angular.js: angular-qart
With Vue 2.x
There is a directive available for using qart.js in Vue.js 2.x : vue-qart
جزئیاتی درباره تغییرات NET Core 2.0.
It has only been about a year since .NET Core 1.0 RC came out. We are now getting close to .NET Core 2.0. We have been playing with .NET Core since the betas and feel like the quality of the 1.0 runtime was very good. Our only complaint has really been odd Visual Studio behavior. We would expect that with 2.0, the adoption of .NET Core is likely to skyrocket.
قالب سیلورلایتی را ایجاد کرده بودم و IE در حالت نمایش عادی این قالب 30 درصد CPU Usage ثابت داشت. علت را هم متوجه نمیشدم؛ چون در این حالت اصلا کدی وجود نداشت که بخواهد CPU Usage ایی را ایجاد کند. یک سری کد XAML جهت نمایش قالب در کنار هم قرار گرفته بودند و همین.
تا اینکه دیروز در وبلاگ رسمی مرتبط با کارآیی برنامههای Silverlight مطلبی منتشر شد که دقیقا مشکل طراحی قالب من هم همان بود:
خلاصه آن:
اگر در حالت نمایش برنامه Silverlight شما (بدون اینکه کدی در حال اجرا باشد) به صورت ثابت CPU Usage بالایی را مشاهده میکنید، پارامتر enableRedrawRegions تگ بارگذاری افزونهی Silverlight را به true مقدار دهی کنید.
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2">
...
<param name="enableRedrawRegions" value="true"/>
...
</object>
پس از فعال سازی این گزینه، برنامه را اجرا کنید. نواحی را که مرتبا در حال ترسیم مجدد هستند، با رنگهای آبی، زرد و صورتی مشاهده خواهید کرد.
در این حالت اگر ناحیهای مرتبا در حال به روز رسانی مشاهده گردید، دقیقا همین ناحیه است که سبب CPU Usage بالا و ثابت برنامه شما شده است و باید فکری به حال آن کرد.
چه زمانی ممکن است این حالت (ترسیمهای مجدد بدون پایان) رخ دهد؟
عموما این مشکل در حین استفاده ناصحیح از افکتهای پیش فرض Silverlight مانند DropShadowEffect رخ میدهد. برای مثال میخواهید قسمتی از قالب شما سایه دار باشد اما نحوهی اعمال این سایه بسیار مهم است.
<Border CornerRadius="3">
<!--High cpu usage-->
<Border.Effect>
<DropShadowEffect BlurRadius="7" Color="#FF1E2224" Opacity="3" ShadowDepth="6" Direction="200" />
</Border.Effect>
<StackPanel>
...
...
در این مثال ابتدا یک border تعریف شده و سپس سایهای به آن اعمال گردیده است. سپس داخل این Border یک StackPanel قرار گرفته است به همراه یک سری از اشیاء زیر مجموعه آن. این کار غلط است! همین مورد به ظاهر ساده 30 درصد CPU Usage ثابت را در برنامه ایجاد کرده بود.
علت چیست؟
با این نحوهی تعریف اشتباه DropShadowEffect ، هر نوع تغییر بصری در مجموعهی Border و StackPanel داخل آن، سبب ترسیم مجدد کل ناحیه میگردد. این تغییر بصری حتی میتواند شامل چشمک زدن یک cursor درون یک TextBox در قسمتی از این ناحیه نیز باشد که با استفاده از ویژگی enableRedrawRegions ، این مورد را به خوبی میتوان مشاهده نمود.
راه حل این مساله کدام است؟
از دو Border استفاده کنید. یک Border با ضخامت کم تنها برای نمایش سایه (که دارای هیچ نوع شیء فرزندی نیست) و Border و StackPanel قبلی هم به همان صورت ابتدایی (البته با حذف DropShadowEffect از آن) باقی بماند.
- WMI Provider MSI still failing to install in 16.6
- View History on context menu in Solution Explorer doesn't do anything
- Cannot generate shim for X509Certificate2 with Visual Studio 2019 16.6.0
- Add Controller and Add New Scaffolded Item dialogs are not showing all data contexts after upgrading Visual Studio Enterprise 16.5.6->16.6.0
- Cannot open new json file
- About Microsoft Visual Studio frozen.
- Visual Studio 2019 16.6.0 Microsoft Fakes Issue
- VSSDK IVsHierarchy Regression in VS 16.6.x
- Windows 10 SDK (10.0.19041.1)- ARM64 memcpy crashes when accessing unaligned uncached memory
- Add script to SQL Server Database project does not open User Scripts list
- Fakes generation with ref argument
- Frequent soft hang with Code Analysis callstack in Open Folder project
- Visual Studio Class Designer dark theme support
- Added support for Text Template Transformation Toolkit (T4) in .NET Core projects
- Separate IntelliCode team completions model acquisition from model production.
- Addressed an issue where users may have experienced critical update or installation failures due to the WMIProvider package that would block use of the IDE. Failures in this component no longer block use of the IDE.
- Fixed a problem causing the product to stop responding when working with Xamarin projects on certain scenarios.
- Fixed a bug where VS would crash when attempting to decrypt an invalid UWP code-signing certificate
در قسمت قبل « کار با اسکنر در برنامههای تحت وب (قسمت اول) » دیدی از کاری که قرار است انجام دهیم، رسیدیم. حالا سراغ یک پروژهی عملی و پیاده سازی مطالب مطرح شده میرویم.
ابتدا پروژهی WCF را شروع میکنیم. ویژوال استودیو را باز کرده و از قسمت New Project > Visual C# > WCF یک پروژهی WCF Service Application جدید را مثلا با نام "WcfServiceScanner" ایجاد نمایید. پس از ایجاد، دو فایل IService1.cs و Service1.scv موجود را به IScannerService و ScannerService تغییر نام دهید. سپس ابتدا محتویات کلاس اینترفیس IScannerService را به صورت زیر تعریف نمایید :
[ServiceContract] public interface IScannerService { [OperationContract] [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetScan")] string GetScan(); }
public class ScannerService : IScannerService { public string GetScan() { // TODO Add code here } }
بر روی پروژهی خود راست کلیک کرده و Add Reference را انتخاب نموده و سپس در قسمت COM، گزینهی Microsoft Windows Image Acquisition Library v2.0 را به پروژهی خود اضافه نمایید.
با اضافه شدن این ارجاع به پروژه، دسترسی به فضای نام WIA برای ما امکان پذیر میشود که ارجاعی از آن را در کلاس ScannerService قرار میدهیم.
using WIA;
public string GetScan() { var imgResult = String.Empty; var dialog = new CommonDialogClass(); try { // نمایش فرم پیشفرض اسکنر var image = dialog.ShowAcquireImage(WiaDeviceType.ScannerDeviceType); // ذخیره تصویر در یک فایل موقت var filename = Path.GetTempFileName(); image.SaveFile(filename); var img = Image.FromFile(filename); // img جهت ارسال سمت کاربر و نمایش در تگ Base64 تبدیل تصویر به imgResult = ImageHelper.ImageToBase64(img, ImageFormat.Jpeg); } catch { // از آنجاییه که امکان نمایش خطا وجود ندارد در صورت بروز خطا رشته خالی // بازگردانده میشود که به معنای نبود تصویر میباشد } return imgResult; }
CommonDialogClass کلاس اصلی در اینجا جهت نمایش فرم کار با اسکنر میباشد و متدهای مختلفی را جهت ارتباط با اسکنر در اختیار ما قرار میدهد که بسته به نیاز خود میتوانید از آنها استفاده کنید. برای نمونه در مثال ما نیز متد اصلی که مورد استفاده قرار گرفته، ShowAcquireImage میباشد که این متد، فرم پیش فرض دریافت اسکنر را به کاربر نمایش میدهد و کاربر از طریق آن میتواند قبل از شروع اسکن، یکسری تنظیمات را انجام دهد.
این متد ابتدا به صورت خودکار فرم تعیین دستگاه اسکنر ورودی را نمایش داده :
و سپس فرم پیش فرض اسکنرهای TWAIN را جهت تعیین تنظیمات اسکن نمایش میدهد که این امکان نیز در این فرم فراهم است تا دستگاههای Feeder یا Flated انتخاب گردند.
خروجی این متد همان عکس اسکن شده است که از نوع WIA.ImageFile میباشد و ما پس از دریافتش، ابتدا آن را در یک فایل موقت ذخیره نموده و سپس با استفاده از یک متد کمکی آن را به فرمت Base64 برای درخواست کننده اسکن ارسال مینماییم.
کدهای کلاس کمکی ImageHelper:
public static string ImageToBase64(Image image, System.Drawing.Imaging.ImageFormat format) { if (image != null) { using (MemoryStream ms = new MemoryStream()) { // Convert Image to byte[] image.Save(ms, format); byte[] imageBytes = ms.ToArray(); // Convert byte[] to Base64 String string base64String = Convert.ToBase64String(imageBytes); return base64String; } } return String.Empty; }
این مثال به سادهترین شکل نوشته شد. کلاس دیگری هم در اینجا وجود دارد و در صورتیکه از اسکنر نوع Feeder استفاده میکنید، میتوانید از کدهای آن استفاده کنید.
جهت رفع این خطا، در قسمت Referenceهای پروژه خود، WIA را انتخاب نموده و از Propertiesهای آن خصوصیت Embed Interop Types را به False تغییر دهید؛ مشکل حل میشود.
به سراغ پروژهی ویندوز فرم جهت هاست کردن این WCF سرویس میرویم. میتوانید این سرویس را بر روی یک Console App یا Windows Service هم هاست کنید که در اینجا برای سادگی مثال، از WinForm استفاده میکنیم.
یک پروژهی WinForm جدید را ایجاد کنید و سپس از قسمت Add Reference > Solution به مسیر پروژهی قبلی رفته و dllهای آن را به پروژه خود اضافه نمایید.
Form1.cs را باز کرده و ابتدا دو متغیر زیر را در آن به صورت عمومی تعریف نمایید:
private readonly Uri _baseAddress = new Uri("http://localhost:6019"); private ServiceHost _host;
حال در رویداد Form_Load برنامه، کدهای زیر را جهت هاست کردن سرویس اضافه مینماییم:
private void Form1_Load(object sender, EventArgs e) { _host = new ServiceHost(typeof(WcfServiceScanner.ScannerService), _baseAddress); _host.Open(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { _host.Close(); }
فایل App.Config پروژهی WinForm را باز کرده و کدهای آنرا مطابق زیر تغییر دهید:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="BehaviourMetaData"> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> <services> <service name="WcfServiceScanner.ScannerService" behaviorConfiguration="BehaviourMetaData"> <endpoint address="" binding="basicHttpBinding" contract="WcfServiceScanner.IScannerService" /> </service> </services> </system.serviceModel> </configuration>
اگر موفق به اجرا نشدید و احیانا با خطای زیر مواجه شدید، اطمینان حاصل کنید که ویژوال استودیو Run as Administrator باشد. مشکل حل خواهد شد.
به سراغ پروژهی بعدی، یعنی وب سایت خود میرویم. یک پروژهی MVC جدید ایجاد نمایید و در View مورد نظر خود، کدهای زیر را جهت صدا زدن متد GetScan اضافه میکنیم.
( از آنجا که کدها به صورت جاوا اسکریپت میباشد، پس مهم نیست که حتما پروژه MVC باشد؛ یک صفحهی HTML ساده هم کافی است).
<a href="#" id="get-scan">Get Scan</a> <img src="" id="img-scanned" /> <script> $("#get-scan").click(function () { var url = 'http://localhost:6019/'; $.get(url, function (data) { $("#img-scanned").attr("src","data:image/Jpeg;base64, "+ data.GetScanResult); }); }); </script>
راه حلهای زیادی برای این مشکل ارائه شده است، و متاسفانه بسیاری از آنها در شرایط پروژهی ما جوابگو نمیباشد (به دلیل هاست روی یک پروژه ویندوزی). تنها راه حل مطمئن (تست شده) استفاده از یک کلاس سفارشی در پروژهی WCF Service میباشد که مثال آن در اینجا آورده شده است.
برای رفع مشکل به پروژه WcfServiceScanner بازگشته و کلاس جدیدی را به نام CORSSupport ایجاد کرده و کدهای زیر را به آن اضافه کنید:
public class CORSSupport : IDispatchMessageInspector { Dictionary<string, string> requiredHeaders; public CORSSupport(Dictionary<string, string> headers) { requiredHeaders = headers ?? new Dictionary<string, string>(); } public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) { var httpRequest = request.Properties["httpRequest"] as HttpRequestMessageProperty; if (httpRequest.Method.ToLower() == "options") instanceContext.Abort(); return httpRequest; } public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { var httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty; var httpRequest = correlationState as HttpRequestMessageProperty; foreach (var item in requiredHeaders) { httpResponse.Headers.Add(item.Key, item.Value); } var origin = httpRequest.Headers["origin"]; if (origin != null) httpResponse.Headers.Add("Access-Control-Allow-Origin", origin); var method = httpRequest.Method; if (method.ToLower() == "options") httpResponse.StatusCode = System.Net.HttpStatusCode.NoContent; } } // Simply apply this attribute to a DataService-derived class to get // CORS support in that service [AttributeUsage(AttributeTargets.Class)] public class CORSSupportBehaviorAttribute : Attribute, IServiceBehavior { #region IServiceBehavior Members void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { var requiredHeaders = new Dictionary<string, string>(); //Chrome doesn't accept wildcards when authorization flag is true //requiredHeaders.Add("Access-Control-Allow-Origin", "*"); requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS"); requiredHeaders.Add("Access-Control-Allow-Headers", "Accept, Origin, Authorization, X-Requested-With,Content-Type"); requiredHeaders.Add("Access-Control-Allow-Credentials", "true"); foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers) { foreach (EndpointDispatcher ed in cd.Endpoints) { ed.DispatchRuntime.MessageInspectors.Add(new CORSSupport(requiredHeaders)); } } } void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } #endregion }
using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher;
[CORSSupportBehavior] public class ScannerService : IScannerService {
کار تمام است، یکبار دیگر ابتدا پروژهی WcfServiecScanner و سپس پروژه هاست را Build کرده و برنامهی هاست را اجرا کنید. اکنون مشاهده میکنید که با زدن دکمهی اسکن، اسکنر فرم تنظیمات اسکن را نمایش میدهد که پس از زدن دکمهی Scan، پروسه آغاز شده و پس از اتمام، تصویر اسکن شده در صفحهی وب سایت نمایش داده میشود.
سورس نگارش کامل دات نت
The referencesource repository contains sources from Microsoft .NET Reference Source that represent a subset of the .NET Framework. This subset contains similar functionality to the class libraries that are being developed in .NET Core. We intend to consult the referencesource repository as we develop .NET Core. It is also for the community to leverage to enable more scenarios for .NET developers.