Sunday, March 8, 2015

C# & PowerShell

This post is to keep a record of what I had done with PowerShell. I have been using PowerShell for quite some time dealing with automation in Active Directory (AD) and System Center Configuration Management (SCCM). I discover that PowerShell can do a lot more thing than I was expected. 

In this post, I will use the example of how to automate in checking a user whether he/she is a member of a particular Active Directory (AD) group. It is written in PowerShell script, but I wanted to explore one more option with C#, knowing the truth that both options will work just fine. The intention is to find out the scripting difference between C# and PowerShell.

Concept

AD has a Directory Service which allow clients to query and manipulate directory objects. There are several methods to access directory service, and the commons are: 
  1. LDAP (Lightweight Directory Access Protocol)
  2. ADSI (Active Directory Service Interface)
In order to check a user whether he/she is a member of a particular AD group, we need to do a query search in AD. The concept is similar to query something from a database. The way how the data is being queried from the database is different from AD. We use SQL to query data from database, but we use LDAP to access directory service to query data from AD.

LDAP is a directory service protocol that run over TCP. Therefore, there are sets of TCP communication between client and directory service to establish session and data exchange. However, we do not need to worry in such low level implementation as we have Directory Service library in .NET Framework.

Implementation

C# version:


Add the Directory Service library reference in to your project.



Create a function for group member search:

public static bool IsGroupMember(string userName, string groupDN)
{
    var searcher = new DirectorySearcher("LDAP://DC=<Your Domain Name>,DC=com");
    searcher.Filter = "(&(objectCategory=person)(CN=" + userName + "))";
    searcher.SearchScope = SearchScope.Subtree;
    searcher.PropertiesToLoad.Add("memberOf");

    var result = searcher.FindAll();

    if (result != null)
    {
        return result[0].Properties["memberOf"].Contains(groupDN);
    }

    return false;
}


The function usage is to pass in the user name that you want to search in the group name.

PowerShell version:

function IsGroupMember($userName, $groupDN)
{
    $searcher = new-object System.DirectoryServices.DirectorySearcher("LDAP://DC=<Your Domain Name>,DC=com")
    $searcher.filter = "(&(objectCategory=person)(CN=$userName))"
    $searcher.SearchScope = "subtree"
    $searcher.PropertiesToLoad.Add("memberOf")

    $result = $searcher.findall()
   
    if ($result -ne $null)
    {
        return $result.Properties.memberof.Contains($groupDN)
    }
}

Hybrid version:


What I like about PowerShell is I can simply invoke any method in C# dll. The benefit of doing so is you can write complex code in C# which you think it is difficult to be written in PowerShell. System engineer will be saved from the horror of coding by just writing simple PowerShell script to call the method in C# which can perform sophisticated execution.

I have created a framework which contains all the functionalities that used to query and manipulate Active Directory related objects and groups, named ADFX. Since this framework was developed in C#, therefore, it can be shared with PowerShell, ASP.NET, windows service, console application, anything which are developed with .NET.

So, instead of having System Engineer to study Directory Service module from .NET Framework, they just need to write a simple PowerShell script below:

Import-Module -Name "C:\Users\Seng-Liang.S.Lee\Desktop\ADFX.dll"

$membership = New-Object ADFX.Membership
$membership.IsGroupMember("<Your User Name>", "<Your Group Distinguished Name>")


Summary

I find that C# and PowerShell are quite the same. Compare the C# code and the PowerScript, both look quite similar. How you write in C#, you can also write the same way in PowerShell, of course except the syntax are different. However, semantically they are the same.

PowerShell is able to import and use with any .NET built component which I like the most. It gives you the flexibility in dividing or separating the complex coding to be done in C# which are Software Engineer expertise, while we leave the easy one to be done in PowerShell which System Engineer can coped with.  



Thursday, January 1, 2015

ASP.NET - MS Chart

Today I want to share about creating charts in ASP.NET web form. There are a lot of awesome chart controls available out there such as Infragistic and Telerik. As you might know, you need to pay for the license to use those 3rd party chart controls. If you have budget constraint, you may opt for free chart control such as Microsoft (MS) Chart.

By default, MS Chart is built-in with Visual Studio 2010 or later. It is under Data category in the design toolbox. MS Chart is available for Winform and Webform.


Chart is useful when you are creating a dashboard or report page. Before you begin creating a chart, you need to have a database with data ready first. In this article, I cover the steps to create a basic nice looking chart which connecting to a SQL server database without writing a single line of code:

I am using a simple address book database containing a contact list for this article. I am creating a pie chart displaying the count of gender from my contact list.


Create Basic Chart

First, drag the chart control from the toolbox to your web page design pane. Then, create a new data source.


Configure Data Source Control

Enter a data source name.




Enter database connection info.



Give a name to the new connect string.



Create a custom SQL statement to display the count of gender.



The query should return only 2 columns, one for X axis and another for Y axis.

I am setting up gender as X axis, and the count as Y axis.




Configure Chart

Back to the chart control, change the chart type to "Pie". Here you can change to any chart type if you do not like pie.



Configure the X Value Member as Gender.

Configure the Y Value Member as Count.


That's it. You can test run your web application, the chart should display now.

I know it look plain and "fugly", we can make it look nicer and customize it to be more meaningful or user friendly.

Change to 3D

We can change the chart to become 3D by customizing the Chart Areas in the properties window.


Locate the Area3DStyle property, then set the Enable 3D value to true.



Display Value in the Pie Area Tooltip

As you can see the pie chart does not show the value in the pie. It is not user friendly and user can never know the actual Y value. Here is how you want to do if you want to let user mouse over to the pie to see the Y value in the tooltip. 

Go to the Series in properties window.




You can ether type the reserved keyword #VAL in the ToolTip property, or you can click the small button there to insert the correct keyword for you.


Click the Insert New Keyword button, then choose the Y value since you want to display that Y value in the pie area.


Click the OK button and you are done.

Your pie chart should look like this now, and when you mouse over to the pie, you can see the actual Y value in the tooltip.


Show Legends

Let's further decorating the chart by adding legend. Go to the Legends in the chart properties window.


Set the Legend title.



Now you can see the legend in your chart, however, it looks like duplicate. Therefore, you can remove the label or replace it with the Y value in the pie.


Replace the Label with Y Value in the Pie

Go back to the same Series properties windows, locate the IsValueShownAsLabel property and then set it to true.



Customize Label

Alternatively, you can display the Y value next to the X value by setting the Label in such format #VALX (#VAL).





Enable Hyperlink in the Pie Area

Imagine that the chart is clickable, and it will bring the user to another page which displaying the detail information. You can enable hyperlink in the pie area.

Go back to the same Series properties window, locate Url property under MapArea category.



Enter the detail page url with the dynamic value. My detail page expect query string named filter. #VALX is the X value which is Male or Female. When the detail page receive the male value, it will display all the contacts with male gender only.

If you want to know all the supported dynamic value or keywords, you can always go to the Keyword Editor to get them.



Once you are done with the configuration, test it out, you will notice the chart is now clickable and the url is formed dynamically.



Clicking the pie will redirect you to the detail page.



Summary

You can do a lot more and customization with MS Chart. This article only cover the very basic chart configuration and screenshots without any coding involve. Feel free to checkout this link: http://msdn.microsoft.com/en-us/library/dd456753(v=vs.140).aspx

By the way, this is my first post of the year 2015. Happy new year everyone!

Sunday, November 2, 2014

How To Deploy Multiple Version of Component In GAC?

Scenario

I believe many programmers like to create shared component or common library in their work. When you see the code can be reusable and it is common for multiple different application, I am sure you will convert it into a framework and then apply them into your projects, so that you can save time from rewriting the same code for the same functionality again and again.

The most common way to deploy the shared component is to put the assembly into your application sub directory (the bin folder) and set the assembly reference in your application. The bad thing is it require you to do a lot of manual work by replicating and deploying the same assembly into every application sub directory.

Solution

We can deploy the shared component to Global Assembly Cache (GAC). Then, make your application reference the assembly from GAC.

Pre-requisite

Before you can deploy your assembly into GAC, you need to sign your assembly first. Just open up Visual Studio, go to your assembly project properties, then at the Signing page, check the "Sign the assembly" box.


Choose <New> from the drop down list to create a new strong name key file.


Simply put a key file name, and protect it with password (optional).

For testing, I have created a simple HelloWorld library to show the assembly version, and it will be used by multiple different application.


Folder Preparation

Create folders for your compiled assemblies for different versions.



Assembly Info

Set the assembly info in the project, and then compile it, finally put into the setup folder as above.


Set the AssemblyVersion and AssemblyFileVersion value for 1.0.0.0 and compile it and keep it into the folder for 1.0.0.0.

Now, make some code changes, then change the version value for 2.0.0.0, compile it and make sure not to overwrite the version 1.0.0.0 assembly file by placing them into different folder.

I changed the code to make it tells me its version is 2.0.0.0.


Installation

Open up Visual Studio Command Prompt. Change directory to where you keep the assembly files.

Run the gacutil.exe command with /i argument to install the assembly to GAC.



Verification

After the installation, you can check your assembly in GAC by running the following command:

gacutil /l HelloWorld


Add Reference

Now, change the assembly reference in your application from bin folder to GAC.

From the Add Reference dialog, you will not find your assembly from there. You have to click the Browse button and locate it from GAC assembly folder which is located at C:\Windows\Microsoft.NET\assembly\GAC_MSIL.


The assemblies in different version are being separated into different folder. The folder name convention is <.net version>_<assembly version>_<public key token>



Deployment

The assemblies installation to GAC is expected be done in both development and production environment. When the application reference the assembly from GAC in the development environment, it will do the same when it is deployed to production server.

Advantage

It is going to save time in deploying the same assembly file to every application and reduce human error. Sometimes developers forget to deploy the required assembly which is used by the application. They will notice it only when they failed to run the application.

Another reason is to save disk space. Instead of duplicating the same assembly into multiple different application sub directory (bin folder), you just have one copy from GAC and every application reference the same file.

Hmm, I find the above 2 advantages are just lame. :)

The good thing that I can think of is when all application are reference one same shared assembly source from GAC, when there is a bug fix for that assembly, you do not need to copy and replace the assembly in every application folder one by one. You can do a "on the fly update" by replacing the assembly in GAC, it will automatically apply the fix to all application which is using it.

The other good thing is side by side versioning. Sometime, you may encounter a situation when there are only a few application require the patch, the rest remain referencing version 1.0.0.0 assembly, those require patch will reference the new version 2.0.0.0 assembly. You can change the affected application assembly reference by using <codeBase> element in config file.


Will write more about using <codeBase> element in config file in my next post if I have time.

Monday, September 1, 2014

JQuery Consume ASP.NET Web API

Today I want to share how to consume ASP.NET Web API by using jQuery. How to do that? Just send HTTP GET, POST, PUT, DELETE request to the Web API with JSON format content. I will use the same address book Web API for testing which I had created in my previous post.

First, add JQuery to your web project by using NuGet.


At the UI designer page, create all the necessary form and fields. I reuse the same UI which I did for my previous post, and added a few extra buttons with JQuery label. These buttons are using AJAX to invoke the Web API.



The following are the Javascript / JQuery that use to invoke the Web API:

HTTP GET

The following method send HTTP GET request to the Web API and get the response data to form a custom grid view (table):

function Get() {
    $.ajax({
        type: 'GET',
        url: 'http://localhost:5593/api/AddressBook',
        dataType: 'json',
        success: function (response) {
            var addressBookList = response;
            CreateTableColumns();
            $.each(addressBookList, function () {
                $('#addressBookTable')
                    .append($('<tr>')
                    .append('<td>' + this.ID + '</td>')
                    .append('<td>' + this.FirstName + '</td>')
                    .append('<td>' + this.LastName + '</td>')
                    .append('<td>' + this.Contact + '</td>')
                    .append('</tr>'));
            });
        }
    });

}

HTTP POST

The following method send HTTP POST request to the Web API to create new record:

function Post() {
    var addressBook = {
        ID: $('input[type="text"][id="ID"]').val(),
        FirstName: $('input[type="text"][id="firstName"]').val(),
        LastName: $('input[type="text"][id="lastName"]').val(),
        Contact: $('input[type="text"][id="contact"]').val()
    };
    $.ajax({
        type: 'POST',
        url: 'http://localhost:5593/api/AddressBook',
        data: addressBook,
        dataType: 'json',
        success: function () {
            //do something here after posted successfully
            alert('Success! Click the Refresh button to see the effect.');
        }
    });
}

HTTP PUT

The following method send HTTP PUT request to the Web API to update an existing record:

function Put() {
    var addressBook = {
        ID: $('input[type="text"][id="ID"]').val(),
        FirstName: $('input[type="text"][id="firstName"]').val(),
        LastName: $('input[type="text"][id="lastName"]').val(),
        Contact: $('input[type="text"][id="contact"]').val()
    };
    $.ajax({
        type: 'PUT',
        url: 'http://localhost:5593/api/AddressBook/' + addressBook.ID,
        data: addressBook,
        dataType: 'json',
        success: function () {
            //do something here after posted successfully
            alert('Success! Click the Refresh button to see the effect.');
        }
    });
}

HTTP DELETE

The following method send HTTP DELETE request to the Web API to delete an existing record:

function Delete() {
    var id = $('input[type="text"][id="ID"]').val();
           
    $.ajax({
        type: 'DELETE',
        url: 'http://localhost:5593/api/AddressBook/' + id,
        success: function () {
            //do something here after posted successfully
            alert('Success! Click the Refresh button to see the effect.');
        }
    });
}

Basically, the concept is the same. When you use the HttpClient class to invoke the Web API during postback, compare to the AJAX way that uses JQuery, you will get the same result. As long as the client is sending the correct and expected HTTP header and content, the Web API will just accept and process it. And of course the user experience is different between postback and AJAX.

You may think that using HttpClient to call Web API during postback is not efficient because of every Web API call, you need to postback and go through all the ASP.NET page life cycle. However, in a Service Oriented Architecture (SOA) environment, when you are separating the web application and web service, especially the web application is sitting in DMZ while the web service is sitting in safe zone, then you have to consume the Web API (web service) by using server code (HttpClient in ASP.NET), refer to this post for sample code. When you are heavily rely on Javascript, jQuery, Angular.js or any client scripting framework to invoke the Web API, then it is not going to work because the invocation is coming from the client browser, it cannot direct access to the Web API which is sitting in the safe zone protected with firewall. Of course, if your Web API is supposed to expose to public, then it is different story.

If you are interested with my complete source code, feel free to download it from HERE.


Sunday, August 24, 2014

ASP.NET Web Form Model Binding + Web API

Nowadays, many people are talking about Web API and some developers came to me and ask for sample code about how to call an ASP.NET Web API by using the HttpClient class library. Today, I want to share how to send HTTP GET, POST, PUT and DELETE to the ASP.NET Web API from a web page that perform simple CRUD operation.

I have created a very simple address book web application that can display and manipulate the data from the Web API. To begin with the ASP.NET Web API development, create a new empty web project from Visual Studio.



Select the Empty template, as I want to create the latest Web API (version 2.2) by getting the latest assembly from NuGet later.


From the newly created project, open NuGet Package Manager, then search for Microsoft ASP.NET Web API 2.2, then install it.


As I am using the Map HTTP Attribute Routes method to define my routes, therefore, create the class WebApiConfig as follow:

public class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();
    }

}

In the same project, add new Global.asax file if not exist. Then, at the Application_Start event, add this line of code:

GlobalConfiguration.Configure(WebApiConfig.Register);

Service

Now, proceed to create a new controller that support Get, List, Create, Update and Delete function by using HttpGet, HttpPost, HttpPut and HttpDelete attributes like following code:

[RoutePrefix("api/AddressBook")]
public class AddressBookController : ApiController
{
    // GET api/<controller>
    [Route]
    [HttpGet]
    public List<AddressBook> Get()
    {
        AddressBookComponent bc = new AddressBookComponent();
        return bc.List();
    }

    // GET api/<controller>/5
    [Route("{id:int}")]
    [HttpGet]
    public AddressBook Get(int id)
    {
        AddressBookComponent bc = new AddressBookComponent();
        return bc.Get(id);
    }

    // POST api/<controller>
    [Route]
    [HttpPost]
    public void Create(AddressBook addressBook)
    {
        AddressBookComponent bc = new AddressBookComponent();
        bc.Create(addressBook);
    }

    // PUT api/<controller>/5
    [Route("{id:int}")]
    [HttpPut]
    public void Put(int id, AddressBook addressBook)
    {
        AddressBookComponent bc = new AddressBookComponent();
        bc.Update(addressBook);
    }

    // DELETE api/<controller>/5
    [Route("{id:int}")]
    [HttpDelete]
    public void Delete(int id)
    {
        AddressBookComponent bc = new AddressBookComponent();
        bc.Delete(id);
    }

}

[RoutePrefix("api/AddressBook")] attribute is used to create a template URL for your API. As the example above, the Web API URL is base at http://localhost:<port>/api/AddressBook

[Routeattribute is used to make an URL that base on the URL defined in RoutePrefix attribute which link to the particular method directly. For this case, I never specify any named parameter to the Route attribute, hence the URL to call this web function is the same, which is http://localhost:<port>/api/AddressBook. The incoming request will route to the correct function base on the supplied HTTP Verb.

[Route("{id:int}")] has specified named parameter. This attribute will route the request URL that contain parameter with integer type to that particular function. In this case, the URL that will hit that function is http://localhost:<port>/api/AddressBook/5

[Route("{id:int}")]
[HttpPut]
public void Put(int id, AddressBook addressBook)

Note that the above HTTP PUT method contain 2 parameters, one is the ID and another is the object. This is the standard PUT method declaration. If you have the method without the ID parameter, you will get HTTP 405 Method Not Allowed error because it will treat it as POST even you had specified HttpPut attribute.

Client

Now, start to create the client that will consume the above Web API. The Web API can only support JSON and XML HTTP content type, and I pick JSON for light weight payload and it is the commonly used format nowadays. We just need to make sure the HTTP request that sent to the Web API contain the content-type : application/json in the HTTP header. And to do that, I use HttpClient class which comes from the Microsoft ASP.NET Web API 2.2 Client Libraries. You can obtain it from NuGet:



In today's topic, I will also cover about how to use model binding in grid view (ASP.NET Web Form not MVC).

NOTE: Before you begin, I expect that you already had an entity or object which defined as a model.

Create a new ASP.NET web form project, then create a new page. Put a grid view in the page, then define the grid view like this:

<asp:GridView ID="addressBookGrid" runat="server"
    ItemType="AddressBookSample.Entities.AddressBook"
    SelectMethod="addressBookGrid_GetData"
    UpdateMethod="addressBookGrid_UpdateItem"
    DeleteMethod="addressBookGrid_DeleteItem"
    DataKeyNames="ID">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
    </Columns>
</asp:GridView>

First, put the model as the ItemType. Then, define the SelectMethod, UpdateMethod and DeleteMethod, when you do it, Visual Studio will automatically suggest, create and map the events for you. Put the model property name in the DataKeyNames which you think it is unique and can be an identifier for your object.

HTTP GET

The following is the implementation for the SelectMethod. It will send HTTP GET request to the Web API, then bind the responded data into the grid view automatically.

public IQueryable<AddressBook> addressBookGrid_GetData()
{
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:5593");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    HttpResponseMessage response = client.GetAsync("api/AddressBook").Result;
    response.EnsureSuccessStatusCode();

    List<AddressBook> addressBooks = response.Content.ReadAsAsync<List<AddressBook>>().Result;

    return addressBooks.AsQueryable();

}

HTTP POST

The following is the implementation for a Create button. I have a form with text boxes and the Create button to let user enter the information that will be sent to the Web API.

protected void btnCreate_Click(object sender, EventArgs e)
{
    AddressBook addressBook = new AddressBook()
    {
        ID = Convert.ToInt32(createID.Text),
        FirstName = createFirstName.Text,
        LastName = createLastName.Text,
        Contact = createContact.Text
    };

    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:5593");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    HttpResponseMessage response = client.PostAsync<AddressBook>("api/AddressBook", addressBook, new JsonMediaTypeFormatter()).Result;
    response.EnsureSuccessStatusCode();
}

HTTP PUT

The following is the implementation for the UpdateMethod. The method will automatically have the id parameter value which you had selected from the grid view, the code will send HTTP GET request to the Web API to retrieve the specific object first, then update the object, finally send the object with HTTP PUT request to the Web API.

public void addressBookGrid_UpdateItem(int id)
{
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:5593");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    HttpResponseMessage response = client.GetAsync("api/AddressBook/" + id).Result;
    response.EnsureSuccessStatusCode();

    AddressBook item = response.Content.ReadAsAsync<AddressBook>().Result;

    // Load the item here, e.g. item = MyDataLayer.Find(id);
    if (item == null)
    {
        // The item wasn't found
        ModelState.AddModelError("", String.Format("Item with id {0} was not found", id));
        return;
    }
    TryUpdateModel(item);
    if (ModelState.IsValid)
    {
        // Save changes here, e.g. MyDataLayer.SaveChanges();
        HttpResponseMessage updateResponse = client.PutAsync<AddressBook>("api/AddressBook/" + id, item, new JsonMediaTypeFormatter()).Result;
        response.EnsureSuccessStatusCode();
    }

}

HTTP DELETE

The following is the DeleteMethod implementation. The method will also automatically have the ID parameter value which you had selected from the grid view, just simply send the ID with HTTP DELETE request to the Web API as follow:

public void addressBookGrid_DeleteItem(int id)
{
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:5593");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    HttpResponseMessage response = client.DeleteAsync("api/AddressBook/" + id).Result;
    response.EnsureSuccessStatusCode();

}


That's it for a simple CRUD web application that deal with Web API. If you are interested with my source code, feel free to download it from HERE.




Send Transactional SMS with API

This post cover how to send transactional SMS using the Alibaba Cloud Short Message Service API. Transactional SMS usually come with One Tim...