C# Enterprise Library Asynchronous Logging

We all know how slow any logging mechanism is, specially when one of the trace listeners is logging to a database. By using .NET 4.0 with it’s Parallel Library (System.Threading.Task) we can easily turn our logger to use fire-forget asynchronous operation.

 Example below uses Enterprise Library 5.0.

Suppose this is your existing LogMessage method:

Just add another method LogMessageAsync with ff code:

Now to log asynchronously just call the LogMessageAsync() method.

 

 

Advertisements

C# Parallel – Call methods with input and return values

In .NET 4.0 they made it easy to start a task/process simultaneously. Code below shows how you can execute two methods with input and return values simultaneously thru the Tasks Factory in System.Threading.Task namespace.

Note: Add System.Threading.Tasks & System.Diagnostics in the using statement.

Code:

 

 

Output:

WCF Using Windows Authentication and SqlRoleProvider over basicHttp

This tutorial is about building a sample WCF Service that makes use of  Windows(Active Directory) as Authentication mechanism and SQLRoleProvider for the Authorization.

1. Lets start by creating a new WCF Service Application. Open VS2010, File New Project under WCF select WCF Service Application. For the name just use the default: WcfService1.

2.  New Project was created, Go to the code of Service1.svc

The goal is: when a client application calls the GetData method, it should have a valid windows account (active directory account) and should be a member of a Role (SqlRole) that we will create later.

Press F6 to compile the project.

3. Next step is to configure service to use Windows and Sql Role Provider.

Right click web.config from WcfService1 project and select Edit WCF Configuration (if this is not available, Click Tools -> WCF Service Configuration Editor then close it, right click the web.config again the menu should be available)

WCF Configuration Editor Opens.

 

WCF Editor Step 1:  Create Service

In the Services Tab, click Create New Service.  In the service type, click Browse -> bin folder-> Select WcfService1.dll -> then Select WcfService1.Service1 then click Open.

Click Next, Contract should be WcfService1.IService1.

Click Next, for the communication mode select HTTP.

Click Next, for the interoperability select Basic Web Services interoperability.

Click Next, for the address type leave it empty, click Finish. New service was added:

Add BaseAddress, Go to Host -> In Base Address click New:  http://localhost:8000/WcfService1

 

WCF Editor Step 2:  Add Binding Configuration

In the Configuration Tab, go to Bindings -> Click New Binding Configuration, select basicHttpBinding from the list. Set the name to basicHttpBindingConfig.

Go to security tab set the following:

(General) Mode: TransportCredentialOnly

(TransportSecurityProperties) TransportClientCredentialType: Ntlm

Set the existing endPoint (basicHttp) to use the binding configuration that we just created.

To do this: go to Endpoints -> Click the first endPoint then on the general tab -> Endpoint Properties ->

Click Binding Configuration then select basicHttpBindingConfig.

 

 

WCF Editor Step 3:  Configure Service Behaviors

Go to Advance -> Service Behaviors

Modify the existing behavior and rename it to WcfService1.ServiceBehavior.

Click Add and select serviceAuthorization from the list.

Go to general Tab and set the ff:

PrincipalPermissionMode: UseAspNetRoles

RoleProviderName: WcfService1RoleProvider (we would configure this later on).

Update the service to use the service behavior. Go to Services -> WcfService1.Service1 in Behavior configuration select WcfService1.ServiceBehavior.

Click File -> Save.

4. After the WCF editor configuration next step is we need to configure the SQLRoleProvider.

SQLRoleProvider Step 1:  Create SqlRoleProvider database

Open Visual Studio 2010 command prompt and type the following command:

aspnet_reqsql -S {YourDatabaseServer} -E -A r

SQLRoleProvider Step 2:  Update Web.config

Copy and paste the following after configuration tag.

  <connectionStrings>
    <!–Setup Connection String for SQLRoleProvider –>
    <add name=”ASPNetDBConnString” connectionString=”Initial Catalog=aspnetdb;data source={YourDatabaseServer};Integrated Security=SSPI;”/>
  </connectionStrings>

Under system.web add the ff:

  <!–Setup Role Provider to be used for authorizations –>
    <roleManager enabled=”true” defaultProvider=”WcfService1RoleProvider” >
      <providers>
        <clear/>
        <add name=”WcfService1RoleProvider
             connectionStringName=”ASPNetDBConnString”
             applicationName=”WcfService1
             type=”System.Web.Security.SqlRoleProvider” />
      </providers>
    </roleManager>

Click File -> Save.

SQLRoleProvider Step 3:  Assign Roles to windows account

We will create a new role named: PowerUsers and only windows account that has this role will be able to execute the GetData method.

Execute the following script:

USE aspnetdb
GO

— Create a new role
EXEC aspnet_Roles_CreateRole ‘WcfService1’, ‘PowerUsers’

— Assign Windows Account to a Role
EXEC aspnet_UsersInRoles_AddUsersToRoles ‘WcfService1’, ‘{YourDomain\YourUserName}‘, ‘PowerUsers’, 8

5. Last step is to implement the role-based security on GetData method.  Go to WcfService1 project and do the ff:

Add reference to: System.Security

Open Service1.svc code – > Add : using System.Security.Permissions

Update GetData method to:

 

Testing:

For the testing i created a console application that calls the webservice with the following code:

 WcfService1.Service1Client client = new WcfService1.Service1Client();
Console.WriteLine(“Data From server: ” + client.GetData(4));
Console.ReadKey();

 

Sample Output (Calling service with an active directory account that is member of PowerUsers role):

 Sample Output (Calling service with an active directory account that is not a member of PowerUsers role):

 To remove the active directory account from a specific role (PowerUsers), execute the following script:

EXEC [aspnet_UsersInRoles_RemoveUsersFromRoles] ‘WcfService1′,’Domain\ActiveDirectoryAccount’, ‘PowerUsers’

Asp.NET – ReportViewer Control not working on IIS7

We recently upgrade our webserver from II6.0 to IIS 7.5, everything works fine except the ReportingViewer control that renders the MSSQL Reporting in Asp.NET. It shows a blank page with missing icons in IE 6.0 and displays missing resource on FireFox.

To solve the problem, you need to add a new Manager Handler in IIS Manager.

Steps are as follows:

1. Open IIS -> Go to Sites – > {Your WebSite} -> In the IIS section double click Handler Mappings

Handler Mappings in IIS7

2.  On the Action (Right side) click Add Managed Handler and set the ff. properties to:

Request Path: Reserved.ReportViewerWebControl.axd

Type: Microsoft.Reporting.WebForms.HttpHandler

Name: ReportViewerWebControl

Click Ok.

Should be fixed now.

 

 

 

Visual Studio 2010 (VS2010) – Project Conversion Errors

I recently converted existing solution using VS2008 to VS2010 successfully but during the recompilation I’ve encountered two errors.

Error# 1:

Cannot import the following key file: {keyFile.pfx}. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_B652311015D642D5 

Solution:

            – Open command prompt and go to location of pfx file then type:

sn -i {keyFile.pfx} {VS_KEY}   //Ex: sn -i rpaulo.pfx VS_KEY_B652311015D642D5 

Error# 2:

The KeyContainer path ‘VS_KEY_B652311015D642D5’ is invalid. KeyContainer must point to an existing file.

Solution:  

In the folder wherein your project (.csproj)  is located create an empty file with fileName = missing VS_KEY.

C# using ThreadPool for multi-threaded application

I’m currently designing an application specifically to handle multiple processing at a certain time. I’ve read all articles about threading, whether to use a background worker, custom thread management, or by using a thread pool. What facinates me is the thread pool, just by passing a workitem viola you have a working multi-threaded application. See simple example below:


using System;
using System.Threading;

public class MyProcess
{

    private ManualResetEvent _doneEvent;

    public MyProcess(ManualResetEvent doneEvent)
    {
        _doneEvent = doneEvent;
    }

    public void MyProcessThreadPoolCallback(Object threadContext)
    {
        int threadIndex = (int)threadContext;
        Console.WriteLine("thread {0} started...", threadIndex);
        StartProcess();
        Console.WriteLine("thread {0} end...", threadIndex);

    // Indicates that the process had been completed
        _doneEvent.Set();
    }

    public void StartProcess()
    {
        // TODO: Add code for processing here

    }

  
}

public class ThreadPoolExample
{
    static void Main()
    {
        const int totalCountToProcess = 10;
        
        ManualResetEvent[] doneEvents = new ManualResetEvent[totalCountToProcess];
        MyProcess[] MyProcessArray = new MyProcess[totalCountToProcess];
      
        // Configure and launch threads using ThreadPool:
        Console.WriteLine("launching tasks...");
        for (int i = 0; i < totalCountToProcess ; i++)
        {
            doneEvents[i] = new ManualResetEvent(false);
            MyProcess p = new MyProcess(doneEvents[i]);
            MyProcess[i] = p;
            ThreadPool.QueueUserWorkItem(p.MyProcessThreadPoolCallback, i);
        }

        // Wait for all threads in pool to finished processing

        WaitHandle.WaitAll(doneEvents);
        Console.WriteLine("All Process are complete.");

           }
}

 

Storing files to mssql database and downloading using Asp.NET

1) First create a new column and set it as varbinary(MAX) for the datatype.

2) Use this code to store the file to database:

            //Read File to Bytes
                    FileStream st = new FileStream(<Location of the file>, FileMode.Open);
                    byte[] fileData= new byte[st.Length];
                    st.Read(fileData, 0, (int)st.Length);
                    st.Close();

                    SqlParameter[] param = new SqlParameter[] { new SqlParameter(“@ID”,<Reference ID>),
                                                    new SqlParameter(“@Data”,fileData)  };

            int i = SqlAccessor.ExecuteNonQuery(<ConnectionString>, SqlAccessor.SqlCommandBuilder(new SqlCommand (<Stored Procedure Name>), param), CommandType.StoredProcedure, out retVal);

 I’ve used Application Blocks to simplify data operation.

To Retrieve the data and to be downloaded from an ASP.NET Page:

3)  I created a function that returns a byte array with ID as parameter

 public static byte[] GetFileFromDB(string id)
    {
        object[] retVal = null;
        byte[] file = null;
        SqlParameter[] param = new SqlParameter[]
        {
            new SqlParameter (“@id”, id)
        };
        string _connString = ConfigurationManager.ConnectionStrings[<ConnectionStringName>].ConnectionString.ToString();
        SqlDataReader reader = SqlAccessor.ExecuteReader(_connString, SqlAccessor.SqlCommandBuilder(new SqlCommand(“SourceFileLogSelFileDataProc”), param), CommandType.StoredProcedure, out retVal);

        if (reader.Read())
        {
            file = (byte[])reader[“<varbinary column that we define in Step 1>“];
        }

        return file;
    }

4) And on the ASP.NET Page itself, on the Page_Load event:

           byte[] fileData = Utils.GetFileFromDB(<ID>);
            Response.ClearContent();
            Response.AddHeader(“Content-Disposition”, “attachment; filename=” + <filename>);
            BinaryWriter bw = new BinaryWriter(Response.OutputStream);
            bw.Write(fileData);
            bw.Close();
            Response.ContentType = ReturnExtension(<file extension>);
            Response.End();

 5) I have another method to determine the ContentType:

  private string ReturnExtension(string fileExtension)
    {
        switch (fileExtension)
        {
            case “.htm”:
            case “.html”:
            case “.log”:
                return “text/HTML”;
            case “.txt”:
                return “text/plain”;
            case “.doc”:
                return “application/ms-word”;
            case “.tiff”:
            case “.tif”:
                return “image/tiff”;
            case “.asf”:
                return “video/x-ms-asf”;
            case “.avi”:
                return “video/avi”;
            case “.zip”:
                return “application/zip”;
            case “.xls”:
            case “.csv”:
                return “application/vnd.ms-excel”;
            case “.gif”:
                return “image/gif”;
            case “.jpg”:
            case “jpeg”:
                return “image/jpeg”;
            case “.bmp”:
                return “image/bmp”;
            case “.wav”:
                return “audio/wav”;
            case “.mp3”:
                return “audio/mpeg3”;
            case “.mpg”:
            case “mpeg”:
                return “video/mpeg”;
            case “.rtf”:
                return “application/rtf”;
            case “.asp”:
                return “text/asp”;
            case “.pdf”:
                return “application/pdf”;
            case “.fdf”:
                return “application/vnd.fdf”;
            case “.ppt”:
                return “application/mspowerpoint”;
            case “.dwg”:
                return “image/vnd.dwg”;
            case “.msg”:
                return “application/msoutlook”;
            case “.xml”:
            case “.sdxl”:
                return “application/xml”;
            case “.xdp”:
                return “application/vnd.adobe.xdp+xml”;
            default:
                return “application/octet-stream”;
        }
    }

Hope this helps.