نظرات مطالب
فراخوانی سرویس های WCF به صورت Async
اگر از روش ChannelFactory استفاده کنید به دلیل دسترسی مستقیم به اسمبلی Service Contract تمام Operation Contract های  تعریف شده در هر سرویس در دسترس خواهد بود. تابع CreateChannel با استفاده از تنظیمات Binding و EndpointAddress یک کانال به سرویس مربوطه خواهد ساخت و هیچ گونه نیازی به Add service reference در این روش نیست.
مطالب
ارث بری کنترلرها در AngularJs
در Angular مکانیزمی وجود دارد که بر اساس آن می‌توان از توابع و خواص تعریف شده در یک کنترلر در سایر کنترلر‌ها نیز استفاده کرد که در واقع از ان به عنوان ارث بری کنترلر‌ها عنوان می‌شود؛ ولی نکته ای که وجود دارد این است که در جاوااسکریپ OOP پشتیبانی نمی‌شود پس چگونه یک  آبجکت کنترلر توابع و خصوصیات کنترلر دیگر را به ارث می‌برد؟ با ذکر یک مثال این مورد را بررسی خواهیم کرد.
ابتدا دو کنترلر به صورت زیر ایجاد می‌کنیم:
var app = angular.module('myApp', []);

app.controller('parentController', function () {
    this.title = 'Title from parent controller';
})

app.controller('childController', function () {
    this.title = 'Title from child controller';
})
در کدهای بالا دو کنترلر به نام parentController و childController ایجاد کردم. از parentController به عنوان کنترلر والد استفاده خواهد شد و قصد داریم که از title آن در کنترلر child استفاده نماییم. View متناظر را به صورت زیر ایجاد خواهیم کرد.
<div ng-app="myApp">
    <div ng-controller="parentController as parentCtrl">
        <div ng-controller="childController as childCtrl">
            <input type="text" ng-model="parentCtrl.title" size="100"/>
            <input type="text" ng-model="childCtrl.title" size="100"/>
        </div>
    </div>
</div>
اولین نکته این است که تگ div تعریف شده برای کنترلر child در محدوده تگ div کنترلر parent قرار گرفته است. دومین نکته این است که از روش controller as برای مقید سازی خواص به المان‌های صفحه استفاده شده است. اگر برنامه را اجرا نمایید خروجی زیر ار مشاهده خواهید کرد.

هر دو کنترلر دارای یک title مجزا هستند ولی با استفاده از یک اشاره گر توانستیم این دو title را تفکیک نماییم.
حال برای دسترسی به title کنترلر parent در سایر کنترلرها کافیست از نام مستعار parentCtrl استفاده نماییم. از آن جا که محدوده کنترلر child در داخل محدوده کنترلر parent است دسترسی به کنترلر parent امکان پذیر می‌باشد.
<div ng-app="myApp">
    <div ng-controller="parentController as parentCtrl">
        <div ng-controller="childController as childCtrl">
            <input type="text" ng-model="parentCtrl.title" size="100"/>
            <input type="text" ng-model="parentCtrl.title" size="100"/>
        </div>
    </div>
</div>
خروجی:

نکته: دسترسی به کنترلر child در کنترلر parent امکان پذیر نیست.

اشتراک‌ها
نگاهی سریع به فریم ورک های MVVM

One year ago MVVM wasn’t very famous. I remember the first article I read about it, about using MVVM to simplify the management of treeview controls. In the last six months, MVVM has been quickly promoted to THE methodology to use when developing WPF applications. During this amount of time, famous WPF developers started to merge their existing MVVM classes into libraries. Those libraries are now known as MVVM frameworks and contain classes designed to help developers to use MVVM in their projects 

نگاهی سریع به فریم ورک های MVVM
فایل‌های پروژه‌ها
PdfRpt-1.9.zip
- Updated the project to use iTextSharp 5.4.1.0.
- Updated the project to use EPPlus 3.1.3. EPPlus 3.1.3 has a reference to System.Web for Uri decoding. So to use PdfReport from now on you need to change your project's target framework to full profile instead of the client profile.
- Added FlushType parameter to FlushInBrowser method. FlushType.Inline displays PDF in the browser instead of showing the download popup.
- Added EFCodeFirstMvc4Sample.
- Added PdfFilePrinter sample.
- Fixed `StartIndex cannot be less than zero` exception when parameter values are defined without defining the actual parameters in SQL data sources.
مطالب
جایگزین کردن StructureMap با سیستم توکار تزریق وابستگی‌ها در ASP.NET Core 1.0
مدل برنامه زیر را در نظر بگیرید:
 public class Service
    {
        public int ServiceId { get; set; }
        public string ServiceName { get; set; }
    }
اینترفیس ICoreService عمل بازیابی اطلاعات کلاس بالا را بر عهده دارد:
 public interface ICoreService
    {
        Service LoadDefaultService();
    }
نتیجه تزریق وابستگی ICoreService برای کنترلر Home در یک پروژه ASP.NET Core 1.0/Asp.Net Mvc 6 چنین استثنایی بود:
An unhandled exception occurred while processing the request
  InvalidOperationException: Unable to resolve service for type 'WebApplication1.Models.ICoreService' while attempting to activate 'WebApplication1.Controllers.HomeController'
Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
 
یعنی زمانیکه Activator میخواست کنترلر Home را فعالسازی کند، نتوانسته وابستگی ICoreService را برای کنترلر فراهم کند. این استثناء در Microsoft.Extensions.Internal.ActivatorUtilities.GetService اتفاق افتاده‌است.

در نسخه‌های قدیمی MVC (منظور نسخه‌های قبل از 6)، برای تزریق وابستگی‌ها از یک Controller Factory یا Dependency Resolver سفارشی استفاده می‌شد. اما در نسخه جدید MVC دیگری خبری از روشهای قدیمی نیست. چونکه یک سیستم تزریق وابستگی توکار، همراه با MVC یکپارچه شده‌است که عملیات تزریق وابستگی‌ها را انجام می‌دهد. سیستم تزریق وابستگی پیش فرض، تنها از 4 حالت عملیاتی پشتیبانی می‌کند:
1- Instance : در همه حال ، تنها یک نمونه خاص ارائه شده و شما مسئول وهله سازی آن هستید.
2- Transient : در هر بار (مثلا در هر درخواست) یک نمونه جدید ساخته میشود.
3- Singleton
4- Scoped : تنها یک نمونه در Scope فعلی ساخته می‌شود.

 تیم Asp.Net برای فراهم آوردن امکان تزریق وابستگی‌ها، تصمیم به انتزاعی کردن ویژگی‌های مشترک محبوبترین Ioc Containerها و اجازه دادن به میان افزارها، جهت ارتباط با این اینترفیس‌ها برای دستیابی به تزریق وابستگی بود.
حال بیایم نگاهی به این اینترفیس‌ها بیندازیم.
اگر به استثنای فوق نگاهی بیندازیم، می‌بینیم که متد GetService یک پارامتر از نوع IServiceProvider را میگیرد. پس اولین اینترفیس IServiceProvider می باشد. همانطور که از اسمش پیداست، کارش فرآهم آوردن سرویس می‌باشد. این اینترفیس فقط یک متد دارد، متد GetService. متد GetService مانند Container.GetInstance در StructureMap می‌باشد. تمام میان افزارها به 2 روش می‌توانند به نمونه‌ای از IServiceProvider دسترسی داشته باشند:
1- Application-Level : از طریق HttpContext.ApplicationServices برای میان افزار قابل دسترسی خواهد بود.
2- Request-Level : از طریق HttpContext.RequestServices. این Service Scope Provider توسط میان افزار در شروع هر Request Pipeline، برای هر درخواست ایجاد و در پایان درخواست توسط همان میان افزار نابود می‌گردد.
اینترفیس بعدی IServiceScope می‌باشد. همان طور که قبلا گفتیم RequestServices یک Scope Container را برای هر درخواست ساخته و در پایان همان درخواست، آن را نابود میکند. اما این کار چگونه مدیریت می‌شود؟ پاسخ، اینترفیس IServiceScope می باشد. این اینترفیس مانند یک Wrapper حول Scope Container عمل میکند و در پایان هر درخواست آن را نابود می‌کند. حال سوال اینجاست که چه کسی مسئول ساخت IServiceScope می‌باشد؟ پاسخ اینترفیس IServiceScopeFactory می‌باشد. این اینترفیس توسط متد CreateScope اقدام به ساخت یک نمونه از اینترفیس IserviceScope می‌نماید.
مورد بعدی ServiceLifeTime می‌باشد. یک Enum که حاوی سه مقدار زیر می‌باشد:
namespace Microsoft.Extensions.DependencyInjection
{
    //
    // Summary:
    //     Specifies the lifetime of a service in an Microsoft.Extensions.DependencyInjection.IServiceCollection.
    public enum ServiceLifetime
    {
        //
        // Summary:
        //     Specifies that a single instance of the service will be created.
        Singleton = 0,
        //
        // Summary:
        //     Specifies that a new instance of the service will be created for each scope.
        //
        // Remarks:
        //     In ASP.NET Core applications a scope is created around each server request.
        Scoped = 1,
        //
        // Summary:
        //     Specifies that a new instance of the service will be created every time it is
        //     requested.
        Transient = 2
    }
}
آخرین مورد کلاس ServiceDescriptor می‌باشد.  این کلاس اطلاعاتی را که Container برای رجیستر کردن سرویس به آنها نیاز دارد، در خود نگهداری می‌کند. این جمله را در نظر بگیرید : " هی Container، وقتی میخواهی این سرویس را رجیستر کنی، اطمینان حاصل کن که Singleton باشد و یک نمونه از نوع X را پیاده سازی کند." تمامی اطلاعات جمله قبل در ServiceDescriptor نگهداری می‌شود.
خوب! حال بیایم تا سرویس خود را رجیستر کنیم. در کلاس StartUp پروژه در متد ConfigurationServices خط زیر را اضافه می‌کنیم:
public void ConfigureServices(IServiceCollection services)
        {                        
            ServiceDescriptor descriptor = new ServiceDescriptor(typeof(ICoreService),typeof(CoreServise),ServiceLifetime.Transient);
            services.Add(descriptor);
            services.AddMvc();          
        }
حال اگر برنامه را اجرا کنیم مشکل برطرف شده است.

ساخت یک Service Descriptor و اضافه کردن آن به سرویسها، فلسفه وجودی میان افزارها را زیر سوال می‌برد. پس بجای ایجاد یک Service Descriptor، از متدهای الحاقی تدارک دیده شده استفاده میکنیم. مثلا بجای دو خط کد بالا می‌توان از کد زیر استفاده نمود:

services.AddTransient<ICoreService,CoreServise>();

حال که یک دید کلی از نحوه کار مکانیزم تزریق وابستگی بدست آوردیم، میخواهیم این مکانیزم را با StructureMap جایگزین کنیم. بدین منظور ابتدا پکیج StructureMap را نصب میکنم.

در مرحله اول باید کلاسهایی را تدارک ببینیم که اینترفیس‌های بالا را پیاده سازی نمایند. یعنی کلاسهای ما باید بتوانند همان کاری را انجام دهند که مکانیزم پیش فرض MVC انجام می‌دهد. 

اولین مورد، کلاس StructureMapServiceProvider می‌باشد.

internal class StructureMapServiceProvider : IServiceProvider
    {
        private readonly IContainer _container;

        public StructureMapServiceProvider(IContainer container, bool scoped = false)
        {            
            _container = container;
        }

        public object GetService(Type type)
        {
            try
            {
                return _container.GetInstance(type);
            }
            catch
            {
                return null;
            }
        }
    }

مورد دوم کلاس StructureMapServiceScope می‌باشد:

internal class StructureMapServiceScope : IServiceScope
    {
        private readonly IContainer _container;
        private readonly IContainer _childContainer;
        private IServiceProvider _provider;

        public StructureMapServiceScope(IContainer container)
        {
            _container = container;
            _childContainer = _container.GetNestedContainer();
            _provider = new StructureMapServiceProvider(_childContainer, true);
        }

        public IServiceProvider ServiceProvider => _provider;

        public void Dispose()
        {
            _provider = null;
            if (_childContainer != null)
                _childContainer.Dispose();
        }
    }

مورد سوم StructureMapServiceScopeFactory می‌باشد:

internal class StructureMapServiceScopeFactory : IServiceScopeFactory
    {
        private IContainer _container;

        public StructureMapServiceScopeFactory(IContainer container)
        {
            _container = container;
        }

        public IServiceScope CreateScope()
        {
            return new StructureMapServiceScope(_container);
        }
    }

مورد بعدی کلاس StructureMapPopulator می‌باشد. وظیفه این کلاس جمع آوری اطلاعات مربوط به سرویس‌ها می‌باشد.

internal class StructureMapPopulator
    {
        private IContainer _container;

        public StructureMapPopulator(IContainer container)
        {
            _container = container;
        }

        public void Populate(IEnumerable<ServiceDescriptor> descriptors)
        {
            _container.Configure(c =>
            {
                c.For<IServiceProvider>().Use(new StructureMapServiceProvider(_container));
                c.For<IServiceScopeFactory>().Use<StructureMapServiceScopeFactory>();

                foreach (var descriptor in descriptors)
                {
                    switch (descriptor.Lifetime)
                    {
                        case ServiceLifetime.Singleton:
                            Use(c.For(descriptor.ServiceType).Singleton(), descriptor);
                            break;
                        case ServiceLifetime.Transient:
                            Use(c.For(descriptor.ServiceType), descriptor);
                            break;
                        case ServiceLifetime.Scoped:
                            Use(c.For(descriptor.ServiceType), descriptor);
                            break;
                    }
                }
            });
        }

        private static void Use(GenericFamilyExpression expression, ServiceDescriptor descriptor)
        {
            if (descriptor.ImplementationFactory != null)
            {
                expression.Use(Guid.NewGuid().ToString(), context => { return descriptor.ImplementationFactory(context.GetInstance<IServiceProvider>()); });
            }
            else if (descriptor.ImplementationInstance != null)
            {
                expression.Use(descriptor.ImplementationInstance);
            }
            else if (descriptor.ImplementationType != null)
            {
                expression.Use(descriptor.ImplementationType);
            }
            else
            {
                throw new InvalidOperationException("IServiceDescriptor is invalid");
            }
        }
    }

و در آخر کلاس StructureMapRegistration می‌باشد:

public static class StructureMapRegistration
    {
        public static void Populate(this IContainer container, IEnumerable<ServiceDescriptor> descriptors)
        {
            var populator = new StructureMapPopulator(container);
            populator.Populate(descriptors);
        }
    }

نهایتاً باید متد ConfigurationServices در کلاس StartUp را اندکی تغییر دهیم.

public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
           
            var container = new Container();
            container.Configure(configure =>
            {
                configure.For<ICoreService>().Use<CoreServise>();
            });

            container.Populate(services);

            return container.GetInstance<IServiceProvider>();
        }

در کد بالا، متد ConfigurationServices به جای آنکه Void برگرداند، نمونه‌ای از اینترفیس IServiceProvider را برمی‌گرداند. حال اگر برنامه را اجرا کنیم، وابستگی‌ها توسط StructureMap تزریق شده و برنامه بدون هیچ مشکلی اجرا می‌شود.

اشتراک‌ها
نحوه استفاده از MVC در ASP.NET Core

It’s No Longer MVC By Default
Cutting Down the List of Default MVC Services
Enabling the MVC Service
MVC Controllers
 ...
 

نحوه استفاده از MVC در ASP.NET Core