basquang™ on clouds

November 25, 2015

Transfer large data with WCF

Filed under: Uncategorized,WCF — basquang @ 3:16 PM
Tags:

[MSDN]: Introduction to Building Windows Communication Foundation Services

[MSDN]: Large Data and Streaming

[MSDN] Transferring large blobs of data with WCF

[MSDN]: Streaming Message Transfer

Transferring large files using WCF

File Transfer with WCF

WCF Streaming: Upload files over HTTP

Transferring large data over the wire using WCF

Passing Large Files in Windows Communication Foundation (WCF) using Streaming and TCP

MTOM vs. Streaming vs. Compression – Large attachments over WCF

Streaming Files (for Upload/Download) in WCF (Message Contracts)

 

November 10, 2015

Secure your WCF Web Services resource references

Filed under: Digital Signature,WCF — basquang @ 3:52 PM
Tags:

You want to secure your WCF web services, you want to sign digital signature on your web service here are some good references

[MSDN]: Using Message Contracts

[MSDN]How to: Set the ProtectionLevel Property

[VS Magazine] Security Considerations and Best Practices for WCF 4 Apps

[MSDN] Message Security with a Certificate Client

[MSDN] Message Security Certificate

[CodeProject] WCF Service Method Level Security using Message Contract

October 26, 2015

TFS 2015: Fail to create Team Project

Filed under: TFS — basquang @ 2:03 PM
Tags:

You may receive following error when try to create TFS Team Project from Visual Studio

Problem: Fail to create team project

Error
The Project Creation Wizard encountered an error while creating reports to the SQL Server Reporting Services on http://win-i20evd01dob/ReportServer/ReportService2005.asmx.
Explanation
The Project Creation Wizard encountered a problem while creating reports on the SQL Server Reporting Services on http://win-i20evd01dob/ReportServer/ReportService2005.asmx. The reason for the failure cannot be determined at this time. Because the operation failed, the wizard was not able to finish creating the SQL Server Reporting Services site.
User Action
Contact the administrator for the SQL Server Reporting Services on http://win-i20evd01dob/ReportServer/ReportService2005.asmx to confirm that the SQL Server Reporting Services server is running and you have sufficient privileges to create a project. Your user account on SQL Server Reporting Services must have Content Manager permission to create a new project. Also, you might find additional helpful information in the project creation log. The log shows each action taken by the wizard at the time of the failure and may include additional details about the error.
Open the log file you may see:
Event Description: TF30162: Task “Populate Reports” from Group “Reporting” failed
Exception Type: Microsoft.TeamFoundation.Client.PcwException
Exception Message: The Project Creation Wizard encountered an error while creating reports to the SQL Server Reporting Services
Exception Message: TF30225: Error uploading report ‘Backlog Overview’: The current action cannot be completed. The user data source credentials do not meet the requirements to run this report or shared dataset. Either the user data source credentials are not stored in the report server database, or the user data source is configured not to require credentials but the unattended execution account is not specified. —> Microsoft.ReportingServices.Diagnostics.Utilities.InvalidDataSourceCredentialSettingException: The current action cannot be completed. The user data source credentials do not meet the requirements to run this report or shared dataset. Either the user data source credentials are not stored in the report server database, or the user data source is configured not to require credentials but the unattended execution account is not specified. (type ReportingUploaderException)
Assumption:
1. The SQL Server Reporting Services is running
2. You are logged in as [DOMAIN]\AccountName to Team Foundation Server to create Team Project
Solution:
You have following items to check:
1. Open Team Foundation Administration Console
a. In Application Tier | Reporting Services Summary has valid Reader Account for example [DOMAIN]\AccountName. If not enter that account
b. In Reporting tab, Edit the Reporting configuration and in Reports tab enter valid account for “Account for accessing datasource” for example [DOMAIN]\AccountName
2. Open Reporting Services Configuration Manager
a. In Encryption Keys tab, try to delete Encrypted Content
b. In Execution Account tab, enter valid account for example [DOMAIN]\AccountName
c. In Database tab, enter try to enter valid account for “Current Report Server Database Credential” for example [DOMAIN]\AccountName
3. Open Report Manager URL at http:/……/Reports
Open security setting for your TFS Reports Database and make sure that your account [DOMAIN]\AccountName. has Content Manager and Team Foundation Content Manager Role Assigment
Hop this help!

September 28, 2015

UWP: Open Store Rating to request user review and rate from your Windows 10 app

Filed under: UWP,windows 10 — basquang @ 4:32 PM
Tags: , , ,

In Windows Phone 8.x, you can use the Marketplace review task to launch the Store or Marketplace and then display the review page for the current app. The code is simple as below

MarketplaceReviewTask marketplaceReviewTask = new MarketplaceReviewTask();
marketplaceReviewTask.Show();

Unfortunately, UWP Windows 10 app does not support this kind of Marketplace review task. So the question is “How to open review page for current app to request user to rate your app on Windows 10?” Solution is, you can use Windows.System.Launcher to launch the ms-windows-store: URI scheme. The URI schema to launches the write a review experience for a product for example are:

Product ID: ms-windows-store://review/?ProductId=9WZDNCRFHVJL
Package Family Name (PFN): ms-windows-store://review/?PFN= Microsoft.Office.OneNote_8wekyb3d8bbwe

And then, in your code, using one of the uriString above

await Windows.System.Launcher.LaunchUriAsync(new Uri(uriString));

For Windows app, using the second schema uri is my recommendation, because you can get PFN dynamically from your code by using Windows.ApplicationModel.PackageId.FamilyName
but Windows.ApplicationModel.PackageId.ProductID is only available for Windows Phone app.

Hope this help!

September 9, 2015

Best Practices: Upgrade to Windows 10 UWP Universal apps

Filed under: Microsoft Technology,UWP — basquang @ 11:29 AM
Tags: ,
Scenario:
– You have Windows Phone 8.x and Windows 8.x apps and want to upgrade the app to UWP Universal for Windows 10 to take advantage of new API platform?
– You just only want to update the Windows app to UWP but leave the phone app version in 8.x for some reason ex: AdMob SDK has not yet supported for Windows Phone 8.1 or later. Here are some best practices for you:
1. To target your UWP app only for Windows 10 devices without phone version
Open the Package.appxmanifest file then edit the Dependencies as below
<Dependencies>
    <!--<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />-->
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.10240.0" MaxVersionTested="10.0.10240.0" />
  </Dependencies>
For this setting, you cannot deploy your app to Emulator or phone devices. And then when you upload the package to store, you will see the instruction below “Device families: Windows.Destop minverion 10.0.10240.0”
11638797_10204463343656324_1794777682_o
For more detail please visit msdn link here
https://msdn.microsoft.com/en-us/library/windows/apps/dn986903.aspx
2. Your UWP app using some extra features as access user appointments, contacts…but you do not see that capabilities in Package.appxmanifest to declare.
The solution is open Package.appxmanifest file then edit the node Capabilities as below:
<Capabilities>
    <Capability Name="internetClient" />
    <uap:Capability Name="appointments" />
  </Capabilities>
For more detail please visit msdn link here
https://msdn.microsoft.com/en-us/library/windows/apps/mt270968.aspx
https://msdn.microsoft.com/en-us/library/windows/apps/dn934741.aspx
3. You want to create settings page for your UWP looks like Microsoft Mail Universal app, which display the page flyout on the right. With Windows 8.x this will be completed by using SettingFlyout template, but the template is not supported for Windows 10 UWP.
Solution is create a new page or usercontrol then change the page/usercontrol class to inherit to Windows.UI.Xaml.Controls.SettingsFlyout. In UWP app the SettingsFlyout control is not visible in template selection but it still there in code.
public sealed partial class SettingsFlyoutControl : SettingsFlyout
<SettingsFlyout
    x:Class="LichViet.UserControls.SettingsFlyoutControl"...>
....
</SettingsFlyout>

Hope this help!

August 7, 2014

[Quartz.NET]: Configure AdoJobStore JobStore

Filed under: Quartz,Quartz.NET — basquang @ 4:05 PM
Tags: ,

JobStore‘s are responsible for keeping track of all the “work data” that you give to the scheduler: jobs, triggers, calendars, etc.

RAMJobStore

RAMJobStore is the simplest JobStore to use, it is also the most performant (in terms of CPU time). RAMJobStore gets its name in the obvious way: it keeps all of its data in RAM. This is why it’s lightning-fast, and also why it’s so simple to configure. The drawback is that when your application ends (or crashes) all of the scheduling information is lost – this means RAMJobStore cannot honor the setting of “non-volatility” on jobs and triggers. For some applications this is acceptable – or even the desired behavior, but for other applications, this may be disasterous.

Configuring Quartz to use RAMJobStore

quartz.jobStore.type = Quartz.Simpl.RAMJobStore, Quartz

To use RAMJobStore (and assuming you’re using StdSchedulerFactory) you don’t need to do anything special. Default configuration of Quartz.NET uses RAMJobStore as job store implementation.

ADO.NET Job Store (AdoJobStore)

AdoJobStore is also aptly named – it keeps all of its data in a database via ADO.NET. Because of this it is a bit more complicated to configure than RAMJobStore, and it also is not as fast. However, the performance draw-back is not terribly bad, especially if you build the database tables with indexes on the primary keys.

To use AdoJobStore, you must first create a set of database tables for Quartz.NET to use. You can find table-creation SQL scripts in the “database/dbtables” directory of the Quartz.NET distribution. If there is not already a script for your database type, just look at one of the existing ones, and modify it in any way necessary for your DB. One thing to note is that in these scripts, all the the tables start with the prefix “QRTZ_” such as the tables “QRTZ_TRIGGERS”, and “QRTZ_JOB_DETAIL”). This prefix can actually be anything you’d like, as long as you inform AdoJobStore what the prefix is (in your Quartz.NET properties). Using different prefixes may be useful for creating multiple sets of tables, for multiple scheduler instances, within the same database.

This article describe simple steps to configure ADO.NET Job Store

  1. Download Quartz.NET package from here http://sourceforge.net/projects/quartznet/files/quartznet/
  2. Run the SQL file tables_sqlServer.sql to create ADO.NET Quartz Job Store tables. After complete you will see list of tables as picture below

     

  3. Create Console Application
  4. Install Quartz.NET NuGet package
  5. Configure logging in App.config as code below

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    
      <configSections>
        <!--<section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />-->
        <sectionGroup name="common">
          <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/>
        </sectionGroup>
      </configSections>
    
      <common>
        <logging>
          <factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
            <arg key="showLogName" value="true"/>
            <arg key="showDataTime" value="true"/>
            <arg key="level" value="INFO"/>
            <arg key="dateTimeFormat" value="HH:mm:ss:fff"/>
          </factoryAdapter>
        </logging>
      </common>
    
      <connectionStrings>
        <add name="QuartzStore" connectionString="Data Source=QUANGNB;Initial Catalog=QuartzNETStore;User ID=sa;Password=********" providerName="System.Data.SqlClient" />
      </connectionStrings>
    
      <!-- 
        We use quartz.config for this server, you can always use configuration section if you want to.
        Configuration section has precedence here.  
      -->
      <!--
      <quartz >
      </quartz>
      -->
    
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
    </configuration>
    

  6. Create quartz.config file and set Build Action = None, Copy to Output Directory = Copy Always. Then add following code to configure Quartz.NET to use ADO Job Store

    # You can configure your scheduler in either <quartz> configuration section
    # or in quartz properties file
    # Configuration section has precedence
    
    quartz.scheduler.instanceName = MyScheduler
    quartz.scheduler.instanceId = AUTO
    quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz 
    
    # this section configures the scheduler to use sqlite as the jobstore
    # to use the RAM store just comment all of this out
    # to use the sqlite store, uncomment all of this 
    quartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartz 
    quartz.jobStore.dataSource = default 
    quartz.jobStore.tablePrefix = QRTZ_ 
    quartz.jobStore.clustered = false
    quartz.jobStore.lockHandler.type = Quartz.Impl.AdoJobStore.SimpleSemaphore, Quartz 
    quartz.jobStore.driverDelegateType = Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz 
    quartz.dataSource.default.provider = SqlServer-20
    quartz.jobStore.useProperties = true
    quartz.jobStore.selectWithLockSQL = SELECT * FROM {0} LOCKS UPDLOCK WHERE LOCK_NAME = @ lockName
    quartz.dataSource.default.connectionStringName = QuartzStore
    quartz.dataSource.default.connectionString = Data Source=QUANGNB;Initial Catalog=QuartzNETStore;User ID=sa;Password=******
    
    # this section configures the scheduler to use sql server ce as the jobstore
    #quartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartz 
    #quartz.jobStore.dataSource = default 
    #quartz.dataSource.default.connectionString = Data Source=quartz.sdf;Persist Security Info=False;
    #quartz.jobStore.tablePrefix = QRTZ_ 
    #quartz.jobStore.clustered = false
    #quartz.jobStore.lockHandler.type = Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz 
    #quartz.jobStore.driverDelegateType = Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz 
    #quartz.dataSource.default.provider = SqlServerCe-351
    #quartz.jobStore.useProperties = true
    

  7. Create Simple Job like this

    public class SimpleJob : IJob
        {
            private static ILog logging = LogManager.GetLogger(typeof(SimpleJob));
    
            public void Execute(IJobExecutionContext context)
            {
                logging.InfoFormat("Hello from job");
            }
        }
    

  8. Using the Job in Program like this

    ILog log = LogManager.GetLogger(typeof(Program));           
    
    // First we must get a reference to a scheduler
    ISchedulerFactory sf = new StdSchedulerFactory();
    IScheduler sched = sf.GetScheduler();
    
    try
    {
    	var startTime = DateTimeOffset.Now.AddSeconds(5);
    
    	var job = JobBuilder.Create<SimpleJob>()
    						.WithIdentity("job1", "group1")
    						.Build();
    
    	var trigger = TriggerBuilder.Create()
    		.WithIdentity("trigger1", "group1")
    		.StartAt(startTime)
    		.WithSimpleSchedule(x => x.WithIntervalInSeconds(10).RepeatForever())
    		.Build();
    
    	sched.ScheduleJob(job, trigger);       
    
    	sched.Start();
    	Thread.Sleep(TimeSpan.FromMinutes(2));
    }
    finally
    {
    	sched.Shutdown(true);
    }         
    

  9. Now run for testing ADO Job Store. The Output like this

    15:56:31:280 [INFO]  Quartz.Impl.StdSchedulerFactory - Quartz.NET properties loa
    ded from configuration file 'C:\Users\Quang\Documents\Visual Studio 2013\Project
    s\QuartzNETSolution\Lesson6\bin\Debug\quartz.config'
    15:56:31:372 [INFO]  Quartz.Util.DBConnectionManager - Registering datasource 'd
    efault' with db provider: 'Quartz.Impl.AdoJobStore.Common.DbProvider'
    15:56:31:372 [INFO]  Quartz.Impl.StdSchedulerFactory - Using default implementat
    ion for object serializer
    15:56:31:383 [INFO]  Quartz.Impl.StdSchedulerFactory - Using custom data access
    locking (synchronization): Quartz.Impl.AdoJobStore.SimpleSemaphore
    15:56:31:384 [INFO]  Quartz.Impl.StdSchedulerFactory - Using default implementat
    ion for ThreadExecutor
    15:56:31:460 [INFO]  Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler S
    ignaller of type: Quartz.Core.SchedulerSignalerImpl
    15:56:31:461 [INFO]  Quartz.Core.QuartzScheduler - Quartz Scheduler v.2.2.4.400
    created.
    15:56:31:491 [WARN]  Quartz.Impl.AdoJobStore.JobStoreTX - Detected usage of SQL
    Server provider without SqlServerDelegate, SqlServerDelegate would provide bette
    r performance
    15:56:31:491 [INFO]  Quartz.Impl.AdoJobStore.JobStoreTX - JobStoreTX initialized
    .
    15:56:31:498 [INFO]  Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz S
    cheduler (v2.2.4.400) 'MyScheduler' with instanceId 'NON_CLUSTERED'
      Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally.
      NOT STARTED.
      Currently in standby mode.
      Number of jobs executed: 0
      Using thread pool 'Quartz.Simpl.SimpleThreadPool' - with 10 threads.
      Using job-store 'Quartz.Impl.AdoJobStore.JobStoreTX' - which supports persiste
    nce. and is not clustered.
    
    15:56:31:500 [INFO]  Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'MySched
    uler' initialized
    15:56:31:501 [INFO]  Quartz.Impl.StdSchedulerFactory - Quartz scheduler version:
     2.2.4.400
    15:56:31:800 [INFO]  Quartz.Impl.AdoJobStore.JobStoreTX - Freed 0 triggers from
    'acquired' / 'blocked' state.
    15:56:31:844 [INFO]  Quartz.Impl.AdoJobStore.JobStoreTX - Recovering 0 jobs that
     were in-progress at the time of the last shut-down.
    15:56:31:844 [INFO]  Quartz.Impl.AdoJobStore.JobStoreTX - Recovery complete.
    15:56:31:861 [INFO]  Quartz.Impl.AdoJobStore.JobStoreTX - Removed 0 'complete' t
    riggers.
    15:56:31:876 [INFO]  Quartz.Impl.AdoJobStore.JobStoreTX - Removed 0 stale fired
    job entries.
    15:56:31:888 [INFO]  Quartz.Core.QuartzScheduler - Scheduler MyScheduler_$_NON_C
    LUSTERED started.
    15:56:36:787 [INFO]  Lesson6.SimpleJob - Hello from job
    15:56:46:619 [INFO]  Lesson6.SimpleJob - Hello from job
    ...
    

     

    While program running Open QRTZ_FIRED_TRIGGERS table

     

    While program running Open QRTZ_JOB_DETAILS table

     

    While program running Open QRTZ_TRIGGERS table

     

    Hope this help!

August 6, 2014

[Quartz.NET]: Configure Job in XML using Quartz plug-in XMLSchedulingDataProcessorPlugin

Filed under: Quartz,Quartz.NET — basquang @ 2:57 PM
Tags: ,

You can initialize the scheduler with predefined jobs and triggers using the XMLSchedulingDataProcessorPlugin. This plugin loads XML file(s) to add jobs and schedule them with triggers as the scheduler is initialized, and can optionally periodically scan the file for changes.The XML schema definition can be found here: http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd

Here are simple steps to use Quartz.NET plugin

  1. Create Console Application
  2. Install Quartz.NET from NuGet
  3. Add logging configuration in App.config as below

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    
      <configSections>
        <sectionGroup name="common">
          <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/>
        </sectionGroup>
      </configSections>
    
      <common>
        <logging>
          <factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
            <arg key="showLogName" value="true"/>
            <arg key="showDataTime" value="true"/>
            <arg key="level" value="INFO"/>
            <arg key="dateTimeFormat" value="HH:mm:ss:fff"/>
          </factoryAdapter>
        </logging>
      </common>
      
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
    </configuration>
    

  4. Create a simple job as code below

    namespace Lesson5
    {
        public class SimpleJob : IJob
        {
            private static readonly ILog log = LogManager.GetLogger(typeof(SimpleJob));
    
            /// <summary>
            /// Called by the <see cref="IScheduler" /> when a
            /// <see cref="ITrigger" /> fires that is associated with
            /// the <see cref="IJob" />.
            /// </summary>
            public virtual void Execute(IJobExecutionContext context)
            {
                // This job simply prints out its job name and the
                // date and time that it is running
                JobKey jobKey = context.JobDetail.Key;
                log.InfoFormat("Executing job: {0} executing at {1}", jobKey, DateTime.Now.ToString("r"));
    
    
                if (context.MergedJobDataMap.Count > 0)
                {
                    ICollection<string> keys = context.MergedJobDataMap.Keys;
                    foreach (string key in keys)
                    {
                        String val = context.MergedJobDataMap.GetString(key);
                        log.InfoFormat(" - jobDataMap entry: {0} = {1}", key, val);
                    }
                }
    
                context.Result = "hello";
            }
        }
    }
    

  5. Create a xml file named as quartz_jobs.xml and set Build Action=Content and Copy to Output Directory=Copy always as below

    <?xml version="1.0" encoding="utf-8" ?>
    <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     				version="2.0">
    
      <processing-directives>
        <overwrite-existing-data>true</overwrite-existing-data>
      </processing-directives>
    
      <schedule>
    
        <job>
          <name>jobName1</name>
          <group>jobGroup1</group>
          <description>jobDesciption1</description>
          <job-type>Lesson5.SimpleJob, Lesson5</job-type>
          <durable>true</durable>
          <recover>false</recover>
          <job-data-map>
            <entry>
              <key>key0</key>
              <value>value0</value>
            </entry>
            <entry>
              <key>key1</key>
              <value>value1</value>
            </entry>
            <entry>
              <key>key2</key>
              <value>value2</value>
            </entry>
          </job-data-map>
        </job>
    
        <trigger>
          <simple>
            <name>simpleName</name>
            <group>simpleGroup</group>
            <description>SimpleTriggerDescription</description>
            <job-name>jobName1</job-name>
            <job-group>jobGroup1</job-group>
            <start-time>1982-06-28T18:15:00.0Z</start-time>
            <end-time>2020-05-04T18:13:51.0Z</end-time>
            <misfire-instruction>SmartPolicy</misfire-instruction>
            <repeat-count>100</repeat-count>
            <repeat-interval>3000</repeat-interval>
          </simple>
        </trigger>
    
      </schedule>
    
    </job-scheduling-data>
    

  6. Loading the job in XML plugin in Program console as code below

    ILog log = LogManager.GetLogger(typeof(Program));
    
    // our properties that enable XML configuration plugin
    // and makes it watch for changes every two minutes (120 seconds)
    var properties = new NameValueCollection();
    properties["quartz.plugin.triggHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin";
    
    properties["quartz.plugin.jobInitializer.type"] = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin";
    properties["quartz.plugin.jobInitializer.fileNames"] = "quartz_jobs.xml";
    properties["quartz.plugin.jobInitializer.failOnFileNotFound"] = "true";
    properties["quartz.plugin.jobInitializer.scanInterval"] = "120";
    
    // First we must get a reference to a scheduler
    ISchedulerFactory sf = new StdSchedulerFactory(properties);
    IScheduler sched = sf.GetScheduler();
    
    // start the schedule 
    sched.Start();
    
    // wait five minutes to give our jobs a chance to run
    try
    {
    	Thread.Sleep(TimeSpan.FromMinutes(5));
    }
    catch (ThreadInterruptedException)
    {
    }
    
    // shut down the scheduler
    sched.Shutdown(true);      
    

Hope this help!

[Quartz.NET]: JobDataMap

Filed under: Quartz,Quartz.NET — basquang @ 2:33 PM
Tags: ,

What is JobDataMap?

The JobDataMap can be used to hold any number of (serializable) objects which you wish to have made available to the job instance when it executes. JobDataMap is an implementation of the IDictionary interface, and has some added convenience methods for storing and retrieving data of primitive types.

In my opinion, JobDataMap used to passing data between Quartz.NET host and Job instance?

Here is one sample code describes how to use JobDataMap.

  1. Create Console Application
  2. Install Quartz.NET from NuGet package
  3. Add logging configuration to App.config as below

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    
      <configSections>
        <sectionGroup name="common">
          <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/>
        </sectionGroup>
      </configSections>
    
      <common>
        <logging>
          <factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
            <arg key="showLogName" value="true"/>
            <arg key="showDataTime" value="true"/>
            <arg key="level" value="INFO"/>
            <arg key="dateTimeFormat" value="HH:mm:ss:fff"/>
          </factoryAdapter>
        </logging>
      </common>
      
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
    </configuration>
    

  4. Define simple ColorJob as code below. This job simple reads data from JobDataMap and write to log

    [PersistJobDataAfterExecution]
    [DisallowConcurrentExecution]
    public class ColorJob : IJob
    {
    	private static readonly ILog log = LogManager.GetLogger(typeof(ColorJob));
    
    	// parameter names specific to this job
    	public const string FavoriteColor = "favorite color";
    	public const string ExecutionCount = "count";
    
    	// Since Quartz will re-instantiate a class every time it
    	// gets executed, members non-static member variables can
    	// not be used to maintain state!
    	private int counter = 1;
    
    	/// <summary>
    	/// Called by the <see cref="IScheduler" /> when a
    	/// <see cref="ITrigger" /> fires that is associated with
    	/// the <see cref="IJob" />.
    	/// </summary>
    	public virtual void Execute(IJobExecutionContext context)
    	{
    
    		// This job simply prints out its job name and the
    		// date and time that it is running
    		JobKey jobKey = context.JobDetail.Key;
    
    		// Grab and print passed parameters
    		JobDataMap data = context.JobDetail.JobDataMap;
    		string favoriteColor = data.GetString(FavoriteColor);
    		int count = data.GetInt(ExecutionCount);
    		log.InfoFormat(
    			"ColorJob: {0} executing at {1}\n  favorite color is {2}\n  execution count (from job map) is {3}\n  execution count (from job member variable) is {4}",
    			jobKey,
    			DateTime.Now.ToString("r"),
    			favoriteColor,
    			count, counter);
    
    		// increment the count and store it back into the 
    		// job map so that job state can be properly maintained
    		count++;
    		data.Put(ExecutionCount, count);
    
    		// Increment the local member variable 
    		// This serves no real purpose since job state can not 
    		// be maintained via member variables!
    		counter++;
    	}
    
    }
    

  5. Using the job in Program as code below:

    ILog log = LogManager.GetLogger(typeof(Program));
    
    // First we must get a reference to a scheduler
    ISchedulerFactory sf = new StdSchedulerFactory();
    IScheduler sched = sf.GetScheduler();
    
    // get a "nice round" time a few seconds in the future....
    DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(null, 10);
    
    // job1 will only run 5 times (at start time, plus 4 repeats), every 10 seconds
    IJobDetail job1 = JobBuilder.Create<ColorJob>()
    	.WithIdentity("job1", "group1")
    	.Build();
    
    ISimpleTrigger trigger1 = (ISimpleTrigger)TriggerBuilder.Create()
    											   .WithIdentity("trigger1", "group1")
    											   .StartAt(startTime)
    											   .WithSimpleSchedule(x => x.WithIntervalInSeconds(10).WithRepeatCount(4))
    											   .Build();
    
    // pass initialization parameters into the job
    job1.JobDataMap.Put(ColorJob.FavoriteColor, "Green");
    job1.JobDataMap.Put(ColorJob.ExecutionCount, 1);
    
    // schedule the job to run
    DateTimeOffset scheduleTime1 = sched.ScheduleJob(job1, trigger1);
    log.Info(string.Format("{0} will run at: {1} and repeat: {2} times, every {3} seconds", 
    	job1.Key, 
    	scheduleTime1.ToString("r"), 
    	trigger1.RepeatCount, 
    	trigger1.RepeatInterval.TotalSeconds));           
    
    // All of the jobs have been added to the scheduler, but none of the jobs
    // will run until the scheduler has been started
    sched.Start();
    
    log.Info("------- Waiting 60 seconds... -------------");
    try
    {
    	// wait five minutes to show jobs
    	Thread.Sleep(300 * 1000);
    	// executing...
    }
    catch (ThreadInterruptedException)
    {
    }
    
    sched.Shutdown(true);          
    

  6. The output similar like this

    14:29:20:014 [INFO]  Quartz.Impl.StdSchedulerFactory - Default Quartz.NET proper
    ties loaded from embedded resource file
    14:29:20:112 [INFO]  Quartz.Impl.StdSchedulerFactory - Using default implementat
    ion for object serializer
    14:29:20:174 [INFO]  Quartz.Impl.StdSchedulerFactory - Using default implementat
    ion for ThreadExecutor
    14:29:20:202 [INFO]  Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler S
    ignaller of type: Quartz.Core.SchedulerSignalerImpl
    14:29:20:203 [INFO]  Quartz.Core.QuartzScheduler - Quartz Scheduler v.2.2.4.400
    created.
    14:29:20:206 [INFO]  Quartz.Simpl.RAMJobStore - RAMJobStore initialized.
    14:29:20:212 [INFO]  Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz S
    cheduler (v2.2.4.400) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
      Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally.
      NOT STARTED.
      Currently in standby mode.
      Number of jobs executed: 0
      Using thread pool 'Quartz.Simpl.SimpleThreadPool' - with 10 threads.
      Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistenc
    e. and is not clustered.
    
    14:29:20:213 [INFO]  Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'Default
    QuartzScheduler' initialized
    14:29:20:213 [INFO]  Quartz.Impl.StdSchedulerFactory - Quartz scheduler version:
     2.2.4.400
    14:29:20:260 [INFO]  Lesson4.Program - group1.job1 will run at: Wed, 06 Aug 2014
     07:29:30 GMT and repeat: 4 times, every 10 seconds
    14:29:20:264 [INFO]  Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzSchedu
    ler_$_NON_CLUSTERED started.
    14:29:20:266 [INFO]  Lesson4.Program - ------- Waiting 60 seconds... -----------
    --
    14:29:30:111 [INFO]  Lesson4.ColorJob - ColorJob: group1.job1 executing at Wed,
    06 Aug 2014 14:29:30 GMT
      favorite color is Green
      execution count (from job map) is 1
      execution count (from job member variable) is 1
    14:29:39:999 [INFO]  Lesson4.ColorJob - ColorJob: group1.job1 executing at Wed,
    06 Aug 2014 14:29:39 GMT
      favorite color is Green
      execution count (from job map) is 2
      execution count (from job member variable) is 1
    14:29:49:999 [INFO]  Lesson4.ColorJob - ColorJob: group1.job1 executing at Wed,
    06 Aug 2014 14:29:49 GMT
      favorite color is Green
      execution count (from job map) is 3
      execution count (from job member variable) is 1
    14:29:59:999 [INFO]  Lesson4.ColorJob - ColorJob: group1.job1 executing at Wed,
    06 Aug 2014 14:29:59 GMT
      favorite color is Green
      execution count (from job map) is 4
      execution count (from job member variable) is 1
    14:30:09:999 [INFO]  Lesson4.ColorJob - ColorJob: group1.job1 executing at Wed,
    06 Aug 2014 14:30:09 GMT
      favorite color is Green
      execution count (from job map) is 5
      execution count (from job member variable) is 1
    14:34:20:252 [INFO]  Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzSchedu
    ler_$_NON_CLUSTERED shutting down.
    14:34:20:257 [INFO]  Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzSchedu
    ler_$_NON_CLUSTERED paused.
    14:34:20:653 [INFO]  Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzSchedu
    ler_$_NON_CLUSTERED Shutdown complete.
    Press any key to continue . . .
    

Hope this help!

August 4, 2014

[Quartz.NET]: Configure NLog for logging

Filed under: Logging,Quartz,Quartz.NET — basquang @ 5:47 PM
Tags: ,

In previous article Configure Logging I described how to configure Logging in configuration file using Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter.

In this article, I will describe how to configure NLog in Quartz application.

Because Quartz.NET using Common.Logging frameworks, so there are two implementations dependency when you want to use NLogLoggerFactoryAdapter:

  • Common.Logging.NLog20 is linked against NLog 2.0.0.2
  • Common.Logging.NLog10 is linked against NLog 1.0.0.505

So you need to install correct version of Common.Logging.NLog and NLog.

  1. Create Console Application
  2. Install Quartz.NET from NutGet. By default at this time NuGet will install following packages. By default Quartz use Common.Logging v2.1.2

    <packages>
      <package id="Common.Logging" version="2.1.2" targetFramework="net45" />
      <package id="Quartz" version="2.2.4" targetFramework="net45" />
    </packages>
    

  3. Add the configuration code below to configure NLog in the App.config file

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
    
      <configSections>
        <sectionGroup name="common">
          <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
        </sectionGroup>
        <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
      </configSections>
    
      <common>
        <logging>
          <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20">
            <arg key="configType" value="INLINE" />
          </factoryAdapter>
        </logging>
      </common>
    
      <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <targets>
          <target name="file" xsi:type="File" layout="${date:format=HH\:MM\:ss} ${logger} ${message}" fileName="${basedir}/logs/logfile.txt" />
        </targets>
        <rules>
          <logger name="*" minlevel="Debug" writeTo="file" />
        </rules>
      </nlog>
    
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>       
    </configuration>
    

  4. Create simple Job like this

    public class SimpleJob : IJob
        {
            private static ILog logging = LogManager.GetLogger(typeof(SimpleJob));
    
            public void Execute(IJobExecutionContext context)
            {
                logging.InfoFormat("Hello from job");
            }
        }
    

  5. Using the job in Program

    ILog log = LogManager.GetLogger(typeof(Program));
    
    // First we must get a reference to a scheduler
    ISchedulerFactory sf = new StdSchedulerFactory();
    IScheduler sched = sf.GetScheduler();
    
    //////////////////
    try
    {
    	var startTime = DateTimeOffset.Now.AddSeconds(5);
    
    	var job = JobBuilder.Create<SimpleJob>()
    						.WithIdentity("job1", "group1")
    						.Build();
    
    	var trigger = TriggerBuilder.Create()
    		.WithIdentity("trigger1", "group1")
    		.StartAt(startTime)
    		.WithSimpleSchedule(x => x.WithIntervalInSeconds(10).WithRepeatCount(4))
    		.Build();
    
    	sched.ScheduleJob(job, trigger);       
    
    	sched.Start();
    	Thread.Sleep(TimeSpan.FromSeconds(30));
    }
    finally
    {
    	sched.Shutdown(true);
    }
    

  6. When press F5 to run the application following error will appear

    Unable to create type ‘Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20’

  7. To resolve this issue. Install Common.Logging.NLog20 from NuGet by running following command in order.NOTE: To use NLong we need to update Common.Logging to version 2.2.0

    Install-Package Common.Logging.NLog20

    Install-Package Common.Logging.Core

    Install-Package Common.Logging -Version 2.2.0

    This command will install following packages

    <packages>
      <package id="Common.Logging" version="2.2.0" targetFramework="net45" />
      <package id="Common.Logging.Core" version="2.2.0" targetFramework="net45" />
      <package id="Common.Logging.NLog20" version="2.2.0" targetFramework="net45" />
      <package id="NLog" version="2.0.0.2000" targetFramework="net45" />
      <package id="Quartz" version="2.2.4" targetFramework="net45" />
    </packages>
    

  8. Now run application again and see the output of logged file in the path bin\debug\logs\logfile.txt

The logged file created by NLog in the configuration you have defined above.

Hope this help!

 

[Quartz.NET]: Configure Logging

Filed under: Logging,Quartz,Quartz.NET — basquang @ 5:02 PM
Tags: ,

Common.Logging can be configured to use different logging frameworks under the hood; namely Enterprise Library, Log4Net and NLog.

However, to keep things simple in last post Get Started we take the simple route and configure logging using code to just log to the console using Common.Logging basic logging mechanism.

Common.Logging.LogManager.Adapter = new Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter { Level = Common.Logging.LogLevel.Info};

This blog post describe how to configure Logging in application configuration file.

  1. Create Console Application
  2. Install Quartz.NET from NuGet
  3. Add following code in the App.config to configure Logging for Quart. In this logging configuration we use ConsoleOutLoggerFactoryAdapter to display log to the Console.Out screen.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
  <configSections>   
    <sectionGroup name="common">
      <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/>
    </sectionGroup>
  </configSections>

  <common>
    <logging>
      <factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
        <arg key="showLogName" value="true"/>
        <arg key="showDataTime" value="true"/>
        <arg key="level" value="INFO"/>
        <arg key="dateTimeFormat" value="HH:mm:ss:fff"/>
      </factoryAdapter>
    </logging>
  </common>
  
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>

  1. Add a simple Job like this. In this Job we use log the execution of the Job by writing the message “Hello World…”

    public class HelloJob : IJob
        {
            //Get logging configuration
            private static ILog _log = LogManager.GetLogger(typeof(HelloJob));
    
            /// <summary> 
            /// Called by the <see cref="IScheduler" /> when a
            /// <see cref="ITrigger" /> fires that is associated with
            /// the <see cref="IJob" />.
            /// </summary>
            public virtual void Execute(IJobExecutionContext context)
            {
    
                // Say Hello to the World and display the date/time
                _log.Info(string.Format("Hello World! - {0}", System.DateTime.Now.ToString()));
            }
    
        }
    

  2. Using the Job in Program class as below
  3. //Get Logging configuration
    ILog log = LogManager.GetLogger(typeof(Program));
    
    // First we must get a reference to a scheduler
    ISchedulerFactory sf = new StdSchedulerFactory();
    IScheduler sched = sf.GetScheduler();
    
    log.Info("------- Scheduling Job  -------------------");
    
    // define the job and tie it to our HelloJob class
    IJobDetail job = JobBuilder.Create<HelloJob>()
    	.WithIdentity("job1", "group1")
    	.Build();
    
    // Trigger the job to run on the next round minute
    ITrigger trigger = TriggerBuilder.Create()
    	.WithIdentity("trigger1", "group1")
    	.StartNow()
    	.WithSimpleSchedule(x => x
    	.WithIntervalInSeconds(10)
    	.RepeatForever())
    	.Build();
    
    // Tell quartz to schedule the job using our trigger
    sched.ScheduleJob(job, trigger);           
    
    // Start up the scheduler (nothing can actually run until the 
    // scheduler has been started)
    sched.Start();
    
    // wait long enough so that the scheduler as an opportunity to 
    // run the job!
    
    // wait 65 seconds to show jobs
    Thread.Sleep(TimeSpan.FromSeconds(60));
    
    // shut down the scheduler
    sched.Shutdown(true);
    

  4. The Console screen output will display the message (execute the job) you have been defined each 10 seconds 6 time (within 60 seconds)

Hope this help

Next Page »

Blog at WordPress.com.