Saturday, December 5, 2009

Entity Framework: EDMX

My previous post showed how to quickly generate the EDMX file and corresponding codebehind classes using VS.NET 2008.

The EDMX itself contains the contents of core model/mapping files for Entity Framework:
  • Conceptual schema definition language (.csdl) - defines the conceptual model.
  • Store schema definition language file (.ssdl) - defines the storage model, aka logical model.
  • Mapping specification language file (.msl) - defines the mapping between the storage and conceptual models.
It also contains information for the IDE to display the EDMX file in Designer View.

Here is an article from the ADO.NET team blog on Extracting CSDL from EDMX.

Here is my generated EDMX file:


<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="PersonModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
<EntityContainer Name="PersonModelStoreContainer">
<EntitySet Name="Person" EntityType="PersonModel.Store.Person" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Profile" EntityType="PersonModel.Store.Profile" store:Type="Tables" Schema="dbo" />
<AssociationSet Name="FK_Profile_Person" Association="PersonModel.Store.FK_Profile_Person">
<End Role="Person" EntitySet="Person" />
<End Role="Profile" EntitySet="Profile" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Person">
<Key>
<PropertyRef Name="PersonID" />
</Key>
<Property Name="PersonID" Type="bigint" Nullable="false" />
<Property Name="LoginID" Type="varchar" Nullable="false" MaxLength="100" />
<Property Name="Password" Type="varchar" Nullable="false" MaxLength="32" />
</EntityType>
<EntityType Name="Profile">
<Key>
<PropertyRef Name="ProfileID" />
</Key>
<Property Name="ProfileID" Type="bigint" Nullable="false" />
<Property Name="PersonID" Type="bigint" Nullable="false" />
<Property Name="FirstName" Type="nvarchar" Nullable="false" MaxLength="100" />
<Property Name="LastName" Type="nvarchar" Nullable="false" MaxLength="100" />
<Property Name="EmailAddress" Type="nvarchar" Nullable="false" MaxLength="255" />
</EntityType>
<Association Name="FK_Profile_Person">
<End Role="Person" Type="PersonModel.Store.Person" Multiplicity="1" />
<End Role="Profile" Type="PersonModel.Store.Profile" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Person">
<PropertyRef Name="PersonID" />
</Principal>
<Dependent Role="Profile">
<PropertyRef Name="PersonID" />
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="PersonModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
<EntityContainer Name="PersonEntities">
<EntitySet Name="Person" EntityType="PersonModel.Person" />
<EntitySet Name="Profile" EntityType="PersonModel.Profile" />
<AssociationSet Name="FK_Profile_Person" Association="PersonModel.FK_Profile_Person">
<End Role="Person" EntitySet="Person" />
<End Role="Profile" EntitySet="Profile" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Person">
<Key>
<PropertyRef Name="PersonID" />
</Key>
<Property Name="PersonID" Type="Int64" Nullable="false" />
<Property Name="LoginID" Type="String" Nullable="false" MaxLength="100" Unicode="false" FixedLength="false" />
<Property Name="Password" Type="String" Nullable="false" MaxLength="32" Unicode="false" FixedLength="false" />
<NavigationProperty Name="Profile" Relationship="PersonModel.FK_Profile_Person" FromRole="Person" ToRole="Profile" />
</EntityType>
<EntityType Name="Profile">
<Key>
<PropertyRef Name="ProfileID" />
</Key>
<Property Name="ProfileID" Type="Int64" Nullable="false" />
<Property Name="FirstName" Type="String" Nullable="false" MaxLength="100" Unicode="true" FixedLength="false" />
<Property Name="LastName" Type="String" Nullable="false" MaxLength="100" Unicode="true" FixedLength="false" />
<Property Name="EmailAddress" Type="String" Nullable="false" MaxLength="255" Unicode="true" FixedLength="false" />
<NavigationProperty Name="Person" Relationship="PersonModel.FK_Profile_Person" FromRole="Profile" ToRole="Person" />
</EntityType>
<Association Name="FK_Profile_Person">
<End Role="Person" Type="PersonModel.Person" Multiplicity="1" />
<End Role="Profile" Type="PersonModel.Profile" Multiplicity="*" />
</Association>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
<EntityContainerMapping StorageEntityContainer="PersonModelStoreContainer" CdmEntityContainer="PersonEntities">
<EntitySetMapping Name="Person">
<EntityTypeMapping TypeName="IsTypeOf(PersonModel.Person)">
<MappingFragment StoreEntitySet="Person">
<ScalarProperty Name="PersonID" ColumnName="PersonID" />
<ScalarProperty Name="LoginID" ColumnName="LoginID" />
<ScalarProperty Name="Password" ColumnName="Password" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="Profile">
<EntityTypeMapping TypeName="IsTypeOf(PersonModel.Profile)">
<MappingFragment StoreEntitySet="Profile">
<ScalarProperty Name="ProfileID" ColumnName="ProfileID" />
<ScalarProperty Name="FirstName" ColumnName="FirstName" />
<ScalarProperty Name="LastName" ColumnName="LastName" />
<ScalarProperty Name="EmailAddress" ColumnName="EmailAddress" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<AssociationSetMapping Name="FK_Profile_Person" TypeName="PersonModel.FK_Profile_Person" StoreEntitySet="Profile">
<EndProperty Name="Person">
<ScalarProperty Name="PersonID" ColumnName="PersonID" />
</EndProperty>
<EndProperty Name="Profile">
<ScalarProperty Name="ProfileID" ColumnName="ProfileID" />
</EndProperty>
</AssociationSetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<edmx:Designer xmlns="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</edmx:Connection>
<edmx:Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true" />
</DesignerInfoPropertySet>
</edmx:Options>
<!-- Diagram content (shape and connector positions) -->
<edmx:Diagrams>
<Diagram Name="Person">
<EntityTypeShape EntityType="PersonModel.Person" Width="1.5" PointX="0.75" PointY="1" Height="1.592306315104167" IsExpanded="true" />
<EntityTypeShape EntityType="PersonModel.Profile" Width="1.5" PointX="3" PointY="0.875" Height="1.7566536458333333" IsExpanded="true" />
<AssociationConnector Association="PersonModel.FK_Profile_Person" ManuallyRouted="false">
<ConnectorPoint PointX="2.25" PointY="1.7961531575520835" />
<ConnectorPoint PointX="3" PointY="1.7961531575520835" /></AssociationConnector></Diagram></edmx:Diagrams>
</edmx:Designer>
</edmx:Edmx>


Here is how it appears in Visual Studio Design View:

Entity Framework Quick Start Tutorial

Entity Framework is an OR/M that began shipping with .NET Framework 3.5 SP1 as part of ADO.NET.


In order to begin working with Entity Framework in VS.NET 2008, right click on a Project and select Add New Item.


Under the New Item dialog window, select data, and choose ADO.NET Entity Data Model.



This will create the EDMX file and corresponding codebehind classes.

Next, we need to choose the model contents, which will either start from a database source, or be a blank, new model.



I chose "Generate from Database Source", the quickest and easiest way to get up and running.

From here, you need to provide information about a database connection and database:



Based on the information provided, you will be given the option to choose database objects to include in the model.



Finally, this will create the EDMX file and corresponding codebehind partial classes for the model.

ADO.NET: Exception Handling

From MSDN entry on System.Data.SqlClient.SqlException:

"Messages that have a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement.

The SqlConnection remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the SqlConnection. However, the user can reopen the connection and continue. In both cases, a SqlException is generated by the method executing the command."

The SqlException itself extends DbException. It contains a collection, Error, of type SqlError.

There are parallel exception classes for OleDb, OracleClient, and Odbc. However, these exception classes did not have the same level of detail and specific behavior as that of the SqlException class.

Wednesday, December 2, 2009

ADO.NET Overview

I have done quite a bit of hands-on development with ADO.NET, but I eventually switched to NHibernate for my DAL.

I also did quite a bit of LINQ-to-SQL (migrated from NHibernate to LINQ-to-SQL), so I am familiar with LINQ syntax.

When I first looked at Entity Framework during DevConnections 2008, I was a bit turned off by its complexity. It was in beta at that point, and I never went back and revisited it. I guess I'll be doing so now, as it is a decent portion (11% according to the Skills Measured) on the Exam 70-561: ADO.NET Application Development.

Starting with a basic review of ADO.NET (just wanted to jot down the basics that I recall off the top of my head, I'll fill in more of the detailed nuances from MSDN later):

Can work in a connected or disconnected data architecture.

Disconnected data architecture:
  • Disconnected architecture makes use of DataSet, DataTable, DataColumn, DataRow to hold a copy of the data in memory.
  • These classes belong to the System.Data namespace and are Database vendor agnostic.
  • One DataSet contains one-to-many DataTables.
  • One DataTable contains one-to-many DataColumns, which represent the structure of the table.
  • The DataTable contains zero-to-many DataRows, which represent the content of the table.
Bridging DataSet to DB implementation (Populating DataSets):
  • DataSets are populated via DataAdapters: calling DataAdapter.Fill(DataSet). The DataTables can also be filled by calling DataAdapter.Fill(DataTable). DataAdapter.Fill is overloaded.
  • DataAdapters are Database vendor specific.
  • DataAdapters use Commands, which are also Database vendor specific. There are properties on DataAdapter: SelectCommand, UpdateCommand, InsertCommand, DeleteCommand.
  • Commands contain a reference to a Connection, which represents the actual physical connection to the Database instance. Connections are Database vendor specific.
Here is a list of the classes (DataAdapter, Command, Connection) and the corresponding version by Database vendor:

DataAdapter
  • System.Data.SqlClient.SqlDataAdapter
  • System.Data.OracleClient.OracleDataAdapter
  • System.Data.OleDb.OleDbDataAdapter
  • System.Data.Odbc.OdbcDataAdapter
Command
  • System.Data.SqlClient.SqlCommand
  • System.Data.OracleClient.OracleCommand
  • System.Data.OleDb.OleDbCommand
  • System.Data.Odbc.OdbcCommand
Connection
  • System.Data.SqlClient.SqlConnection
  • System.Data.OracleClient.OracleConnection
  • System.Data.OleDb.OleDbConnection
  • System.Data.Odbc.OdbcConnection

ADO.NET studies and AdventureWorks DB

After setting up SQL Server 2008 Express Edition and the Microsoft SQL Server Management Studio, I went to download the AdventureWorks sample database.

Apparently, AdventureWorks is the new sample database, taking the place of the classic Northwind sample database. Downloaded it from the following site:

Microsoft SQL Server Product Samples: Database - Release SQL Server 2008 SR3

This turned out to be much more painful than expected, mainly because the AdventureWorks DB requires both Full Text Search and FileStream.

Here are the Prereqs for the AdventureWorks DB.

Unfortunately, I installed the DB Runtime with SSMS only (no Advanced Services).

I'm going to uninstall the SQL Server 2008 instance and install the version that includes:
  • DB Runtime
  • SSMS
  • Advanced Services

Tuesday, December 1, 2009

Passed Microsoft Exam: 70-503

Today I passed Exam 70-503: .Microsoft .NET Framework 3.5 - Windows Communication Foundation.

This was the hardest of the exams I've taken thus far in going for the
Microsoft Certified Professional Developer (MCPD): Enterprise Application Developer 3.5.

I probably spent the most time studying for this exam (other than the Fundamentals), and am glad to be done with it.

Now, onto ADO.NET, LINQ, and Entity Framework.

Monday, November 30, 2009

WCF Security

The Thanksgiving break was nice ... pretty much spent all my time (other than family time) studying from my WCF book and reading WCF articles online.


Starting to focus on Security in WCF.

Security in WCF is classified as either Transport-level Security or Message-level Security.

Transport-level Security is known as point-to-point security (also termed "hop-to-hop security" on Microsoft sites), and secures data as it is transferred across the network. It is vulnerable to messages traveling through intermediary, unsecured points between the sender and receiver of the Message.

Message-level Security is known as end-to-end security, and involves securing the message itself, ensuring message privacy and integrity, regardless of the path taken from sender to receiver.

There are 3 Security modes:
  1. Transport
  2. Message
  3. TransportWithMessageCredential
These are described on this MSDN article about Programming WCF Security.

Once the security mode has been selected, the developer needs to select a Client Credential Type. The clientCredentialType is an attribute on the transport or message tag under security in the binding. There are different clientCredentialTypes available for transport or message.

Here is an MSDN article on Selecting a Credential Type.

The final step is to set the Client Credential Values.

Sunday, November 29, 2009

WCF Hosting

There are several options available when choosing a Service Host for a WCF Service. These include:
  • IIS
  • WAS (Windows Process Activation Services), built into Vista and Windows Server 2008
  • Windows Service (starts and stops with the OS)
The selection of a Service Host does not have any impact on the development process of the WCF Service itself.

Service hosts must do the following:
  1. Instantiate System.ServiceModel.ServiceHost
  2. Add endpoints to the host
  3. Start the host listening
Several notes about host selection:

  • WAS enables hosting of services that do not rely upon HTTP.
  • When hosting in IIS, must choose a binding that specifies HTTP as the transport, such as basicHttpBinding, wsHttpBinding, wsDualHttpBinding. Choosing a binding based on a different transport causes an error.
WCF supports an ASP.NET Compatibility mode, which allows ASP.NET to provide the hosting environment (and thus the service can get to ASP.NET implicit objects and methods). In order to enable compatibility mode, two things must be done:
  1. aspNetCompatibilityEnabled attribute of must be set to true
  2. AspNetCompatibilityRequirements must be set to Allowed at Service Behavior level.

Friday, November 27, 2009

WCF Study Resources

Links I found while studying:

WCF Bindings

Bindings are pre-packaged channel stacks. WCF provides 12 bindings:

  • basicHttpBinding - WS-I Basic Profile, and ASMX Web Services
  • wsHttpBinding - advanced WS-* Web Services, WS-Security, WS-Transactions
  • wsDualHttpBinding - Duplex Web Services
  • webHttpBinding - REST / POX-based Web Services using XML and JSON.
  • netTcpBinding - communication between two .NET systems
  • netNamedPipeBinding - Communication between one or more .NET Systems.
  • netMsmqBinding - Asynch communication via MSMQ
  • netPeerTcpBinding - P2P networking applications
  • msmqIntegrationBinding - Sending and receiving messages via MSMQ
  • wsFederationHttpBinding - Web Services that use Federated Identity
  • ws2007HttpBinding - same as wsHttpBinding, with enhanced support for changes in 2007
  • ws2007FederationHttpBinding - same as wsFederationHttpBinding, with enhanced support for changes in 2007
Bindings that start with "net" are used to support WCF between .NET applications. Bindings that start with "ws" are used to support interoperability with non .NET applications.

netNamedPipeBinding is for binary, local machine communication only (and consequently has the highest performance metrics). The address will take the following form: net.pipe://localhost/{service}.

netTcpBinding addresses will take the format: net.tcp://{hostname}.

netMsmqBinding addresses will take the form: net.msmq://{hostname}/[private/public]/{queueName}. The default port is 1801 and cannot be changed.

WCF Channels

WCF Applications communicate by sending messages across channels.

There are two types of channels: Transport Channels and Protocol Channels. Transport channels sit at the lowest layer and provide the actual transport for messages. Protocol channels provide security, transactions, sessions, and message reliability.

Channels are layered upon one another, to create a channel stack. Bindings represent channel stack configurations, and simply the process of creating and referencing channel stacks.

The 3 communication patterns:
  • One-way
  • Request-Response
  • Duplex
are supported by 10 different channel shapes. There are actually 5 different shapes, each with 2 versions (one that supports sessions, and one that does not. Here are the 5 shapes:
  • IOutputChannel (IOutputSessionChannel). Supports one-way communication.
  • IInputChannel (IInputSessionChannel). Supports one-way communication.
  • IDuplexChannel (IDuplexSessionChannel). Supports duplex communication.
  • IRequestChannel (IRequestSessionChannel). Supports request-response communication.
  • IResponseChannel (IResponseSessionChannel). Supports request-response communication.
Channel listeners and channel factories will listen for messages.

Channel listeners can be closed without closing down the channel on which they were listening.

Channel factories are responsible for closing down their channels.

ICommunication object is the basis of all communication objects in WCF, which includes channels, channel factories, and channel listeners. Communication objects go through states: Created, Opening, Opened, Closing, Closed, and Faulted. Events are thrown when the Communication object transitions between these states.

Thursday, November 26, 2009

WCF Contracts

3 Types of WCF Contracts:


  1. Service contracts: Maps class methods to WSDL services.

  2. Data contracts: Maps .NET classes to XML Schemas.

  3. Message contracts: Maps .NET classes to SOAP messages

I read through the section entitled "Service Contracts" and the message exchanges described follow standard communication patterns:

  • Request-Response (Synchronous and Asynchronous)

  • One-way

  • Duplex communication

I started working with the [DataContract] and [DataMember] attributes, which handle the manner in which model classes are mapped to the XSD ComplexType.

Very cool stuff.

Here's some sample code I wrote:



using System;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace WinCommFoundation
{
[DataContract (Namespace="http://philiptenn.com/wcf", Name="PersonComplexType")]
public class Person
{
[DataMember(Name = "FirstName", Order = 1, IsRequired = true)]
public String FirstName;

[DataMember(Name = "LastName", Order = 2, IsRequired = true)]
public String LastName;

[DataMember(Name = "ID", Order = 0, IsRequired = true)]
public Int64 PersonId;

[DataMember(Name = "Birthday", Order = 3, IsRequired = true)]
public DateTime DateOfBirth;

[DataMember(Name = "LastAccessDate", Order = 4, IsRequired = false)]
public DateTime LastAccessed;

}
[ServiceContract]
public interface IPersonService
{
[OperationContract]
Person GetPerson();
}

public class PersonService : IPersonService
{
public Person GetPerson()
{
Person person = new Person();
person.PersonId = 0L;
person.FirstName = "John";
person.LastName = "Smith";
person.DateOfBirth = DateTime.Parse("1990-10-01");
person.LastAccessed = DateTime.Now;
return person;
}
}

public class Service
{
public static void Main(string[] args)
{
ServiceHost serviceHost = new ServiceHost(typeof(PersonService));
serviceHost.Open();

Console.WriteLine("Running PersonService, hit any key to end.");
Console.ReadLine();
serviceHost.Close();
}
}
}


And here is the corresponding App.config file:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WinCommFoundation.PersonService" behaviorConfiguration="personServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/wcfTest"/>
</baseAddresses>
</host>
<endpoint address=""
binding="basicHttpBinding"
contract="WinCommFoundation.IPersonService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>

<behaviors>
<serviceBehaviors>
<behavior name="personServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>


This created the following XSD:


<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" targetNamespace="http://philiptenn.com/wcf" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://philiptenn.com/wcf">
<xs:complexType name="PersonComplexType">
<xs:sequence>
<xs:element name="ID" type="xs:long" />
<xs:element name="FirstName" nillable="true" type="xs:string" />
<xs:element name="LastName" nillable="true" type="xs:string" />
<xs:element name="Birthday" type="xs:dateTime" />
<xs:element minOccurs="0" name="LastAccessDate" type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
<xs:element name="PersonComplexType" nillable="true" type="tns:PersonComplexType" />
</xs:schema>

Wednesday, November 25, 2009

WCF Client

Visual Studio .NET 2008 provides a GUI interface for "Add Service Reference", which calls to svcutil.exe under the covers.


I created a new Windows Console project in VS.NET 2008 and right clicked on the project and selected "Add Service Reference", and was presented with the following dialog:





This generated the Client Proxy necessary to consume the Service. It actually created a new folder under my project called "Service References", and beneath that, an additional folder for each Service Reference.


Here is the client code that uses the generated proxy.


using System;
using WCFClient.ServiceReference;

namespace WCFClient
{
public class Client
{
public static void Main(string[] args)
{
GreetingServiceClient serviceClient = new GreetingServiceClient();
Console.Write(serviceClient.GetGreeting("Philip", "Tenn"));
serviceClient.Close();
Console.ReadKey();
}
}
}


My thoughts on this:

  • Really like being able to choose the namespace of the generated client proxy.

  • Creating the client code itself was simple ... just construct an instance of the GreetingServiceClient, and call the methods as if they were any regular class method. The details are hidden under the covers of WCF.

WCF Services

Next up: Exam 70-503: Windows Communication Foundation

Windows Communication Foundation Notes:



WCF was released as part of .NET 3.0, initially code-named Indigo. It is intended to support distributed applications and evolve from past attempts such as Remoting, Web Services, DCOM, and MSMQ.


It is focused on hosting, consuming, securing services to support distributed application.


It was enhanced as part of .NET 3.5 to support integration with Windows Workflow Foundation, as well as Web-based application support.

The "ABCs" of WCF are:

  • Address

  • Binding

  • Contract



Communication between WCF Clients and Service are done via channels. Messages are passed through the channel. The channel itself is composed of binding elements, which are stacks. The service endpoint provides a contract / interface. The WCF binding will define the channel, and there are built in bindings, such as BasicHttpBinding, WSHttpBinding, NetTcpBinding, and others.



Here is the list and definition of WCF System-Provided Bindings.

I wrote the following as my first WCF Service, based on examples in the book and on the Web.


using System;
using System.ServiceModel;
using System.Text;

namespace WCF
{
[ServiceContract]
public interface IGreetingService
{
[OperationContract]
String GetGreeting(String firstName, String lastName);
}

public class GreetingService : IGreetingService
{
public string GetGreeting(String firstName, String lastName)
{
StringBuilder greeting = new StringBuilder();
greeting.Append("Hello ");
greeting.Append(" ");
greeting.Append(firstName);
greeting.Append(" ");
greeting.Append(lastName);
return greeting.ToString();
}
}

public class Service
{
public static void Main(string[] args)
{
ServiceHost serviceHost = new ServiceHost(typeof(GreetingService), new Uri("http://localhost:8000/wcfTest"));
serviceHost.AddServiceEndpoint(typeof (IGreetingService), new BasicHttpBinding(), "");
serviceHost.Open();

Console.WriteLine("Running GreetingService, hit any key to end.");
Console.ReadLine();
serviceHost.Close();
}
}
}



The code sample above uses programmatic definition of the Service Address URI as well as the Bindings.

However, we could also declaratively define these in a web.config or app.config Configuration file.

Here is an example of an app.config file that provides the address, bindings, and exposes the Metadata Exchange information.



<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WCF.GreetingService" behaviorConfiguration="greetingServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/wcfTest"/>
</baseAddresses>
</host>
<endpoint address=""
binding="basicHttpBinding"
contract="WCF.IGreetingService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>

<behaviors>
<serviceBehaviors>
<behavior name="greetingServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>



When I open the URL: http://localhost:8000/wcfTest, I see the following in my browser:


Passed Microsoft Exam: 70-505

Yesterday, I passed Exam 70-505: .NET Framework 3.5 Windows Forms Application Development.

In the evening, I went out and bought a book on Windows Communication Foundation. The book I got is "Essential Windows Communication Foundation For .NET Framework 3.5", by Steve Resnick, Richard Crane, and Chris Bowen. It's part of Addison Wesley's .NET Development Series.

I sat down at Borders and browsed through all the WCF books they had, and this one seemed to have the most information presented in a digestable manner.

I'm starting studies on WCF immediately.

Monday, November 23, 2009

SQL Server 2008 Express Edition

Since I'm going to be studying for an ADO.NET test soon, I figured I would need an instance of SQL Server on my home computer.

I went to Microsoft.com to download the free SQL Server 2008 Express Edition. I've used SQL Server 2005 in the past, but really haven't worked with 2008 yet.

I was presented with the following options:





I went to install "Runtime with Management Tools", since I have no need for reporting. I definitely need the runtime, and the SQL Server Management Studio that I worked with in SQL Server 2005 was pretty cool.

When I began the install process (they have a Web Installer now), I started getting an error message:





Turned out the problem was the the instance of SQL Server 2005 that was installed (probably as one of the options that I chose, though I can't recall) as part of my Visual Studio .NET 2008 Installation.

I went into Control Panel and uninstalled SQL Server 2005 Express Edition, and all of its dependencies (pretty much every program that started with the name "SQL Server"). I figured I'd uninstall the dependencies first, and finally SQL Server 2005 Express Edition last.

Turned out this was a big mistake. It basically ended up orphaning my SQL Server 2005 Express Edition, so that I couldn't fully uninstall it. So I ended up downloading and reinstalling SQL Server 2005 Express Edition SP3, and then uninstalling it.

This worked, and when I went back to install SQL Server 2008 Express, I got a new error message:





Getting closer! Just need to install VS.NET 2008 SP1.

Sunday, November 22, 2009

Deployment: ClickOnce

When reading about the Skills Measured for the Exam 70-505: Microsoft .NET Framework 3.5, Windows Forms Application Development, it appeared that a relatively high percentage of the exam (15%) was dedicated to ClickOnce.

I had done a lot of reading in the past about deployment strategies for Microsoft .NET Windows Application Deployment (ClickOnce, Installer, XCOPY), but really don't have much hands-on application, so I figured I'd begin my studies here.

Found the following starting point on MSDN about Deploying .NET Framework Applications.

Notes about ClickOnce:
  • Only supported by VB.NET and C# applications, not C++.
  • Publish Windows Forms, Windows Presentation Framework (WPF, formerly Avalon when I first started working with it), and Console Applications to a Publish Location (Web Server, Network drive, FTP Server)
  • ClickOnce Applications subject to CAS, Security Zone will depend on the Publish Location.

Passed Microsoft Exam: 70-564

I passed Microsoft Exam 70-564: Pro: Designing and Developing ASP.NET Applications Using the Microsoft .NET Framework 3.5 on Tuesday, November 17.

There really wasn't any new studying required from Exam 70-562: Microsoft .NET Framework 3.5, ASP.NET Application Development.

Things got incredibly busy at work this week (actually thought about rescheduling my exam, but I asked my manager and he said I should proceed with my exam).

So I passed it, got my Microsoft Certified Professional Developer (MCPD) distinction, and spent the rest of the week putting in tons of hours at work on optimizing SQL and performance tuning. Didn't touch my Microsoft Press books for the rest of the week.

I'm hoping to get back into it, starting with Windows Forms, when things calm down a bit at work.

Saturday, November 14, 2009

Passed Microsoft Exam: 70-562

I passed Microsoft Exam 70-562: Microsoft .NET Framework 3.5, ASP.NET Application Development on Friday (11/13/09).

Probably can't go into much detail due to the terms of the exam, all I can say is that it was painful and I walked out of the exam with a horrible migraine. Instead of writing sample code, I just crammed using the Microsoft Press book, Skills Measured, MSDN and various blogs.

Planning on going straight onto 70-564: Pro: Designing and Developing ASP.NET Applications Using the Microsoft .NET Framework 3.5

To be honest, I'm not planning to study for this test much (if at all). I have a feeling that having recently prepared thoroughly for and taken both the .NET Fundamentals and the ASP.NET App Dev exams, there should not be any new material.

Even if there is, hopefully, it should be a small enough percentage of the overall test that my preparation for the first 2 exams should be enough to pass.

ASP.NET Data Controls

I found an excellent article that highlighted the similarities and differences among ASP.NET Data Controls:

Understanding the Differences Among the DataGrid, DataList, and Repeater

I've used the DataGrid and Repeater in the past (never really used the DataList), but more often than not, I'd lose track of the subtle differences between ASP.NET data controls.

The biggest problem in my view is that the name really does not provide a clear picture of either the usage or the rendered HTML of the particular Data Control.

There's also the ListView (and its DataPager) that was introduced in 3.5. I've not had a chance to write actual code using ListView ... hoping to write at least some sample code, but I've been so busy cramming for the ASP.NET exams that I haven't been doing much hands-on .NET Development.

It's ironic, but I've found that most certification exams require a high-level understanding of a vast array of topics, and even when they occasionally delve in-depth, one is better served by reading quickly through a large book (like my Microsoft Press book) than writing an application that utilizes certain technologies (such as writing a Photo Gallery that uses ListView, Membership Providers, etc.)

Saturday, November 7, 2009

ASP.NET Page Lifecycle events

From my ASP.NET experience, understanding the Page Lifecycle and what occurs at each point is one of the most confusing (and important) aspects of ASP.NET development.

Here are the 2 MSDN pages that I've gone over several times and memorized:

There is also several pages in my Microsoft Press book that are very similar to these MSDN pages.

The challenge is remembering each of the events, and what is appropriate to do at that particular event. For example:

  • PreInit - Set Master Page, Set Theme, create dynamic controls
  • Init - Controls have been initialized, theme skins applied. Initialize control properties.
  • InitComplete - Perform tasks that require initialization has been completed.
  • PreLoad - Perform any processing that should occur before Load.
  • Load - Set properties in controls and establish database connections
  • Control Events (calling of delegates based on events raised, should check Page.IsValid if there are any Validator controls).
  • LoadComplete - Perform tasks that require load has been completed.
  • PreRender - Prior to this event occurring, Page calls EnsureChildControls for all controls, including itself. Also, all data bound controls have DataBind method called.
  • SaveStateComplete - ViewState has been encoded and saved, then this event occurs.
  • Render - Page object calls Render on every control.
  • Unload - event occurs for each Control, finally for the Page. Do cleanup, close database connections.
*sigh* I like ASP.NET, but I've tended to only use a few of these Lifecycle events (PreInit and Load) to keep things simple. They are SO granular, as you can see from the list above, and it's difficult to remember what-goes-where.

Wednesday, November 4, 2009

Microsoft Certification Studies: 70-562

Next up ... Exam 70-562: Microsoft .NET Framework 3.5, ASP.NET Application Development

The starting point for ASP.NET is the System.Web.UI namespace.

I've spent a lot of time on the MSDN site for this namespace, having done a lot of ASP.NET development work. I've practically lived on the API for Page and Control, and sites that document the ASP.NET Page Lifecycle, so this is more review and refamiliarization than anything.

However, I am sure there will be some new material I haven't been exposed to yet.

I'm also using the Microsoft Press book "Microsoft .NET Framework 3.5 - ASP.NET Application Development" by Mike Snell, Glenn Johnson, Tony Northrup, and GrandMasters.

Read through the first 2 chapters this evening.

Passed Microsoft Exam: 70-536

I passed my Microsoft .NET 70-536 exam today. Woo-hoo!

My primary approach to preparing for this exam was the Microsoft Press book that covered the exam, as well as just pouring over the MSDN FCL documentation.

I also wrote a lot of little test programs (some of which I ended up posting on my blog). I've done a lot of .NET development, but the Skills Measured (from Microsoft's site) covered a lot of aspects of the .NET Framework that I've never used (nor had a reason to use).

The biggest ones being:

- COM / Interop. I've done standalone .NET Windows Forms clients, installer programs, and a Globalized ASP.NET Website. Never had a reason / need to interface with COM. I just studied the book on this, read articles on sites like CodeProject.

- System.Diagnostics. Coming from the Java world, I had always used log4j for my logging needs, so log4net seemed like a good, practical solution. Consequently, I never needed to use Systems.Diagnostics.

This evening, after work, I immediately began studying for 70-562: ASP.NET Application Development.

It feels like being in college again, taking final exams. :-) Good times!

Tuesday, November 3, 2009

Systems Diagnostics

For some reason, this is one of those topics I've really dreaded about the exam. I guess it's because most of my .NET Development has been done on ASP.NET, using log4net for my logging.

Consequently, I've tended to stay away from the Systems.Diagnostic (the stuff that writes to the Windows Event Log).

Ah, well, this is a good time to learn it, since the exam covers it.

Here is a test program I wrote to use the System.Diagnostic.EventLog, as well as System.Diagnostic.Debug.


using System;
using System.Diagnostics;

namespace Diagnostics
{
class Program
{
static void Main(string[] args)
{
String applicationEventSource = "Test Diagnostic Application";
if (!EventLog.SourceExists(applicationEventSource))
{
EventLog.CreateEventSource(applicationEventSource, "Application");
}

// Use static method to write an entry. Default EventLogEntryType is Information
EventLog.WriteEntry(applicationEventSource, "Hello, world!");

// Try using instance-specific methods to write a test error
EventLog eventLog = new EventLog("Application");
eventLog.Source = applicationEventSource;
eventLog.WriteEntry("Test error", EventLogEntryType.Error);

// Test debug
Debug.Listeners.Add(new ConsoleTraceListener());
String testString = "Company";
Debug.WriteLine("Test");
Debug.WriteLineIf(testString != "My Company", "Incorrect Company");
Console.ReadKey();
}
}
}

Sunday, November 1, 2009

Cryptography

I've been playing with the System.Security.Cryptography namespace, making sure I'm familiar with the classes here.

I'm really starting to feel good about taking the .NET certification exam 70-536, think I'll do it next week. I've been studying hours every night, and going over the Microsoft Press study book by Tony Northrup, as well as just reading the MSDN .NET FCL.

Wrote the following test program that shows how to create an MD5 hash.


using System;
using System.Security.Cryptography;
using System.Text;


namespace SecurityTest
{
class Program
{
static void Main(string[] args)
{
String unencryptedPassword = "password";
String encryptedPassword = EncryptPassword("MD5", unencryptedPassword);
Console.WriteLine("Encrypted password is: '" + encryptedPassword + "'");
Console.ReadKey();
}

public static String EncryptPassword(String cryptAlgorithm, String unencryptedPassword)
{
HashAlgorithm hashAlgorithm = HashAlgorithm.Create(cryptAlgorithm);

byte[] hash = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(unencryptedPassword));

StringBuilder s = new StringBuilder();
foreach (byte b in hash)
{
s.Append(b.ToString("x2").ToLower());
}
string password = s.ToString();

return password;
}
}
}

Saturday, October 31, 2009

Authentication and Authorization

Well, it's Halloween, and in between going to answer the doorbell, I'm still studying for my Microsoft .NET 70-536 exam.

Can't think of anything I'd rather be doing on Halloween than studying and writing code. :-)

Authentication and Authorization classes reside in the System.Security.Principal namespace.

The following classes and interfaces exist in this namespace:

  • WindowsIdentity - Represents a Windows or AD user account.
  • WindowsPrincipal - Provides access to a user's group memberships. From my study book, "You can use the WindowsPrincipal class to determine which groups a user is a member of. To query for built-in groups, pass to the WindowsPrincipal.IsInRole method a member of the System.Security.Principal.WindowsBuiltInRole".
  • GenericIdentity - For simple, non-Microsoft directory service user account.
  • GenericPrincipal - For simple, non-Microsoft directory service groups.
  • IIdentity - For custom users.
  • IPrincipal - For custom groups.
  • WindowsBuiltInRole (enum) - local Windows groups that are common in NT, 2000, XP. Include: User, PowerUser, Administrator, Guest, AccountOperator, SystemOperator, PrintOperator, BackupOperator, and Replicator.



Here is sample code to get the current user's group memberships:


using System;
using System.Threading;
using System.Security.Principal;

namespace IdentityPrincipal
{
class Program
{
static void Main(string[] args)
{
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
Console.WriteLine("Current User: '{0}", currentIdentity.Name);

// Two ways to get the currentPrincipal.
// 1. Through the WindowsPrincipal constructor passing in currentIdentity.
//WindowsPrincipal currentPrincipal = new WindowsPrincipal(currentIdentity);

// 2. Through the Thread.CurrentPrincipal property (after setting the Principal Policy of the
// current domain. For this sample program, we will use this method.
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal currentPrincipal = (WindowsPrincipal) Thread.CurrentPrincipal;

if (currentPrincipal.IsInRole(WindowsBuiltInRole.User))
{
Console.WriteLine("Current User is a User");
}
if (currentPrincipal.IsInRole(WindowsBuiltInRole.Guest))
{
Console.WriteLine("Current User is a Guest");
}
if (currentPrincipal.IsInRole(WindowsBuiltInRole.PowerUser))
{
Console.WriteLine("Current User is a Power User");
}
if (currentPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
{
Console.WriteLine("Current User is an Administrator");
}
Console.ReadKey();
}
}
}

Wednesday, October 28, 2009

Streams and Serialization

I started working on Streams and Serialization. I've worked with both of these concepts in-depth in Java (and have worked with System.IO Namespace in .NET), so this was an enjoyable area of study.

The biggest challenge was just remembering the class names, and not getting them mixed up with Java.

Here is a small test program I wrote that uses Binary Serialization and File Streams.

It serializes a strongly-typed list of IDs to a binary file, and deserializes it back. I had concerns about casting on formatter.Deserialize(stream), but it appeared to work okay. I do think that this is a dangerous practice, though, but am not sure of a better way to do it in a typesafe manner.


using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace Serialization
{
class Program
{
static void Main(string[] args)
{
String serializedFilePath = @"c:\myObject.bin";
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
IList<int> myIds = new List<int> { 10, 20, 30, 40, 50, 60, 70, 80, 90, 99 };
FileStream fs = new FileStream(serializedFilePath, FileMode.Create, FileAccess.ReadWrite);

try
{
Console.WriteLine("About to serialize");
formatter.Serialize(ms, myIds);
formatter.Serialize(fs, myIds);

}
finally
{
ms.Close();
fs.Close();
}

// Now, we will deserialize from the file
try
{
Console.WriteLine("About to deserialize");
fs = new FileStream(serializedFilePath, FileMode.Open, FileAccess.Read);
IList<int> deserializedIds = (IList<int>) formatter.Deserialize(fs);

StringBuilder sBuilder = new StringBuilder();
foreach (int id in deserializedIds)
{
sBuilder.Append(" ");
sBuilder.Append(id);
}
Console.WriteLine("Deserialized List: " + sBuilder.ToString());
}
finally
{
fs.Close();
}
Console.ReadKey();
}
}
}

Tuesday, October 27, 2009

Configuration Management

I wrote the following test class to practice using classes in System.Configuration, especially ConfigurationManager.


using System;
using System.Configuration;
using System.Linq;
using System.Text;

namespace TestConfigurationManager
{
class Program
{
static void Main(string[] args)
{
// Get the AppSetting entries
for (int i=0; i < ConfigurationManager.AppSettings.Count; i++)
{
Console.WriteLine("AppSetting key: " + ConfigurationManager.AppSettings.AllKeys[i] + ", value: " + ConfigurationManager.AppSettings[i]);
}

// Get the Machine Config located at windows_root\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config
Configuration machineConfig = ConfigurationManager.OpenMachineConfiguration();

ProtectedConfigurationSection protectedConfigSection = (ProtectedConfigurationSection) machineConfig.GetSection("configProtectedData");

Console.WriteLine("Protected provider default: " + protectedConfigSection.DefaultProvider);
Console.WriteLine("Here are the providers: ");
foreach (ProviderSettings settingsColl in protectedConfigSection.Providers)
{
Console.WriteLine("\t{0}", settingsColl.Name);
}

Console.ReadKey();
}
}
}
/*
Output:

AppSetting key: username, value: ptenn
AppSetting key: password, value: pass
AppSetting key: domain, value: mydomain
Protected provider default: RsaProtectedConfigurationProvider
Here are the providers:
RsaProtectedConfigurationProvider
DataProtectionConfigurationProvider

*/

Multithreaded Applications

I wrote the following test program, which makes use of several classes in the System.Threading namespace:


using System;
using System.Threading;

namespace ThreadingApp
{
public class Program
{
static void Main(string[] args)
{
Program program = new Program();
program.RunApp();
Console.ReadKey();
}

public void RunApp()
{
ThreadPool.QueueUserWorkItem(ThreadMethod, "Thread 1");
ThreadPool.QueueUserWorkItem(ThreadMethod, "Thread 2");
ThreadMethod("Thread 3");
ThreadPool.QueueUserWorkItem(ThreadMethod, "Thread 4");
Console.WriteLine("Main thread exits.");

Thread myThread = new Thread(new ThreadStart(ThreadCallback));
myThread.Name = "My Thread";
myThread.Priority = ThreadPriority.Highest;
Console.WriteLine("From runapp, {0}.ThreadState={1}", myThread.Name, myThread.ThreadState);
myThread.Start();

}

void ThreadCallback()
{
Console.WriteLine("Calling ThreadCallback");
Console.WriteLine("{0}.ThreadState={1}", Thread.CurrentThread.Name, Thread.CurrentThread.ThreadState);
}

void ThreadMethod(Object stateInfo)
{
String state = (String) stateInfo;
if (Thread.CurrentThread.IsBackground)
{
Console.WriteLine("background thread: " + state);
}
else
{
Console.WriteLine("foreground thread: " + state);
}
}
}
}

/*
Resulting output:

foreground thread: Thread 3
Main thread exits.
background thread: Thread 1
background thread: Thread 2
background thread: Thread 4
From runapp, My Thread.ThreadState=Unstarted
Calling ThreadCallback
My Thread.ThreadState=Running

*/

Service Controllers and System.ServiceProcess namespace

From the Skills being Measured:

"Implement, install, and control a service."

These are Windows Services (the same services that we all know and love under the Control Panel -> Administration Tools -> Services).

The relevant classes, structs, enums are in the following namespace:

System.ServiceProcess

Here are some of the key classes:

  • ServiceBase - base class that should be extended by any new class that will run as a Windows Service. Implementing a service involves extending ServiceBase and providing behavior that will occur when the service is started, stopped, paused, continued. All services that extend ServiceBase should implement OnStart and OnStop, and may also implement OnPause and OnContinue.
  • ServiceController - represents an existing Windows Service, allows for the service to be stopped, started, manipulated, and information to be obtained about it. Here is an excellent example of a ServiceController on CodeProject. GetServices is a static method that will return an array of ServiceController objects.
  • ServiceControllerPermission - From MSDN: Allows control of code access security permissions for service controllers. I could not find any samples on how to use ServiceControllerPermission class, nor could I find any properties or methods in ServiceController that demonstrated how to use the ServiceControllerPermission.
  • ServiceInstaller - Installs a Service class (class that extends System.ServiceProcess.ServiceBase). Should be called by installation utility. The method ServiceInstaller.Install will be automatically called by the install utility, and if anything goes wrong, ServiceInstaller.Rollback will be called.
  • ServiceProcessInstaller - Installs a Service class. Can be used to specify that the Service will run under a different account (such as the Local System account).
  • SessionChangeDescription (struct) - Contains reason for Terminal Services session change. Has a property, Reason, which is an enum of SessionChangeReason.
  • SessionChangeReason (enum) - See SessionChangeDescription.Reason property.

Monday, October 26, 2009

Collections

The System.Collections namespace contains non-generic classes and interfaces that pertain to gathering and sorting collections of objects and value types.

Here is the MSDN reference for System.Collections.

Classes:




  • ArrayList - Array whose size is dynamically increased as required. Implements IList, IEnumerable. Method arrayList.Add will add an object to the array. Objects can be removed by calling arrayList.Remove(o : Object). ArrayLists can be sorted. Any type of object can be stored, including null.


  • BitArray - Compact Array of bits (bool values).


  • CaseInsensitiveComparer - Compares objects for equivalence, ignoring case on Strings.


  • CollectionBase - Abstract base class for strongly-typed Collection of objects.


  • Comparer - Compares objects for equivalence, case-sensitive for Strings. Default implementation of IComparer interface.


  • DictionaryBase - abstract base class for key-value pair collections. Each entry is stored as a DictionaryEntry struct (structure that represents a key-value pair). Consequently, a foreach iteration over an implementation of DictionaryBase will be a foreach (DictionaryEntry de : dictionary).

  • Hashtable - Implementation of key-value pair collection. If an add is called, but there is already a DictionaryEntry with this key, an Exception is thrown. hashtable.ContainsKey should be called to make sure that it doesn't exist.

  • Queue - FIFO collection of objects. Method Enqueue adds to the Queue, Dequeue removes from the queue using FIFO. Peek will return the same value as Dequeue, but will not actually remove the object from the Queue.

  • ReadOnlyCollectionBase - Similar to CollectionBase, only read-only.

  • SortedList - Collection of key-value pairs, where the keys are sorted.

  • Stack - LIFO collection of objects. Method Push adds to the Stack, Pop removes from the Stack using LIFO. Peek will return the same value as Pop, but will not actually remove the object from the Stack.

Structs:



  • DictionaryEntry - represents a key-value pair for a collection that implements IDictionary.

Interfaces:



  • ICollection - base interface for classes in System.Collections namespace. Extends IEnumerable.

  • IComparer - contract defines a single method, Compare(a : Object, b: Object) : int. Will return negative if a is less than b, 0 if a and b are equal, positive if a is greater than b.

  • IDictionary - collection of key-value pairs (which are DictionaryEntry structs). 3 types of IDictionary implementations: read-only, fixed-size, variable-size.

  • IEnumerable - Provides GetEnumerator method, which must be implemented in order to support the foreach keyword.

  • IList - Collection of objects that can be accessed by index.

Wednesday, October 21, 2009

Exceptions

Since I come from a Java background, there was a bit of adjustment to .NET Framework approach to Exception handling.

The biggest difference between Java and .NET Exception Handling:

Java has checked exceptions, .NET does not have checked exceptions


No checked exceptions = no "throws" keyword, and no "throws" on method signatures.


Checked exceptions in Java always made me feel "boxed in" when I was programming, and made me spend a lot of time on "scaffolding" code.


This difference took me a bit of adjustment time. However, I found that I preferred the .NET approach to exception handling. I always hated working with APIs or Frameworks where the infrastructure code threw a lot of Exceptions, so I was forced to have huge try-catch blocks, and I wasn't really sure what to do in the event of an Exception.


A classic example is working with just about any class in the java.io or java.nio packages.


Back to Exceptions in .NET ... I often refer to the following section of MSDN Website:

Best Practices for Handling Exceptions


Notes about Exception handling:


  • System.Exception is the root class for all Exceptions. System.SystemException and System.ApplicationException derive from System.Exception.

  • Initially, I thought that all custom application exceptions should derive from System.ApplicationException (hence the name). However, the best practices on MSDN suggest that this is not necessarily true.

Generics

Generics allow us to create classes that are not bound to a specific type, and must provide generic functionality for all types. It can be used to provide type-safety during compile-time.

Here is a sample program I wrote to demonstrate how to create a Generic class. I intentionally avoided using for the type, to show this is not a requirement.


using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace SystemTypesCollections
{
public class GenericsTest<ZX>
{
public ZX MyVal { get; set; }

public override string ToString()
{
if (MyVal is String)
{
return "My String is: '" + MyVal + "'";
}
else if (MyVal is int)
{
return "I am an Integer: " + MyVal;
}
else
{
return "I am an object";
}

}
public GenericsTest(ZX val)
{
MyVal = val;
}
}

public class Program
{
static void Main(string[] args)
{
GenericsTest<int> g1 = new GenericsTest<int>(5);
GenericsTest<String> g2 = new GenericsTest<string>("Hello, world");
GenericsTest<IList> g3 = new GenericsTest<IList>(new ArrayList());

System.Console.WriteLine(g1);
System.Console.WriteLine(g2);
System.Console.WriteLine(g3);
}
}
}



Output result:
I am an Integer: 5
My String is: 'Hello, world'
I am an object

Value Types

As I've been studying for the Microsoft .NET certification test, I am posting my study notes on my blog.

Value Types


Value Types are types that are copied when passed in as arguments (passed by value).


Value Types are stored on the stack (whereas Reference Types are stored in the Heap). Here is an excellent series of articles about Heap vs. Stack:


C# Heap(ing) Vs Stack(ing) in .NET: Part I


C# Heap(ing) Vs Stack(ing) in .NET: Part II


C# Heap(ing) Vs Stack(ing) in .NET: Part III


C# Heap(ing) Vs Stack(ing) in .NET: Part IV


There are two kinds of Value Types:



  • Built-in value types. These include:


  1. Byte (8-bit unsigned integer, byte)

  2. SByte (8-bit signed integer, byte)

  3. Int16 (16-bit signed integer, short)

  4. Int32 (32-bit signed integer, int)

  5. Int64 (64-bit signed integer, long)

  6. UInt16 (16-bit unsigned integer, ushort)

  7. UInt32 (32-bit unsigned integer, uint)

  8. UInt64 (64-bit unsigned integer, ulong)

  9. Single (32-bit single-precision floating point, float)

  10. Double (64-bit double-precision floating point, double)

  11. Boolean (boolean value true/false, boolean)

  12. Char (16-bit Unicode, char)

  13. Decimal (128-bit, decimal)

  14. IntPtr (signed integer, depends on underlying platform)

  15. UIntPrt (unsigned integer, depends on underlying platform)
  • User-defined Value Types.

The User-defined Value Types will extend System.ValueType or System.Enum. I copied the Complex Number Representation example from MSDN into VS.NET 2008 and played around with it.

Structs are also Value Types. This article from CodeProject covers Enums and Structs.

Tuesday, October 20, 2009

Nullable types

A new language construct as of the .NET 2.0 Framework is Nullable types. Basically, it allows one to extend a Value Type (such as int, bool), and make it nullable.

Here's a small sample class I wrote to experiment with using Nullable Types.


namespace Project
{
public class DataTest
{
// The syntax T? (in C#) is shorthand for System.Nullable<T>, where T is a value type. The two forms are interchangeable.
private int? age = null;
private System.Nullable<system.int32> weight = null;

public int? Age
{
get { return age; }
set { age = value; }
}

public int? Weight
{
get { return weight; }
set { weight = value; }
}

public DataTest()
{}

public DataTest(int? myAge, int? myWeight)
{
Age = myAge;
Weight = myWeight;
}

///
/// Return String displaying age and weight
///

///
public override string ToString()
{
if (Age.HasValue && Weight.HasValue)
{
return "Your age is: " + Age.Value + ", and your weight is: " + Weight.Value;
}
else
{
return "No age or weight entered";
}
}
}
}


The following is a good reference for Nullable Types: Introduction to .Net Framework 2.0 Nullable Types.

Microsoft Certification Studies: 70-536

Today, I'm starting studies for Microsoft .NET certification. It looks like the first step in the journey to any certification path is the 70-536: Microsoft .NET Framework Application Development Foundation.

First question that immediately came to mind: is the test given in C# or VB? Part of the beauty of the .NET Framework is the underlying CLR, BCL (base class libraries) and language-independence. However, this has also been a bit of a challenge for me during past .NET development projects.

I'm a C# guy, myself. Sometimes I'll find excellent blog entries, posts, or forum responses of what I want to do, but the examples are in VB. Now, I can stumble through VB code examples, but it feels like reading text in a foreign language, whereas reading C# feels like reading something in my native language (English).

I found the answer to my question here:
http://www.proprofs.com/forums/index.php?showtopic=20207

I'll definitely be selecting C# for my exam.

Tuesday, July 7, 2009

VMware Server and Fedora Core 11, Part 4

At this point, I have been happily able to run existing VMs.

However, I went to create a new VM today, and my connection to local host dropped immediately.

I went to examine my log files (/var/log/vmware) and found the following core dump:

Jul 07 10:13:41: | VMHSWorkerMain done : thread id = 6737
Jul 07 10:13:41: | Caught signal 6 -- pid 6737
Jul 07 10:13:41: | SIGNAL: eip 0xf7f71430 esp 0xf7bfac4c ebp 0xf7bfac64
Jul 07 10:13:41: | SIGNAL: eax 0x0 ebx 0x1a51 ecx 0x1a52 edx 0x6 esi 0x3b edi 0x5c3ff4
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfac4c : 0xf7bfac64 0x00000006 0x00001a52 0x004817c1
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfac5c : 0x005c3ff4 0xf7bfad84 0xf7bfad8c 0x00483092
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfac6c : 0x00000006 0xf7bfad04 0x00000000 0x005c3ff4
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfac7c : 0x00000001 0xf7bfac98 0x00000000 0xf79007f0
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfac8c : 0x00000000 0xf7900010 0x00000018 0x00020000
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfac9c : 0x00000001 0x00001000 0x00000000 0xffffffc8
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfacac : 0x00530163 0xf7900010 0x005c5ec0 0x0000006e
Jul 07 10:13:41: | SIGNAL: stack 0xf7bfacbc : 0x005c76a8 0xf7900010 0x00020a60 0x005c3ff4
Jul 07 10:13:41: | Backtrace:
Jul 07 10:13:41: | Backtrace[0] 0xf7bfa688 eip 0x80c9d62
Jul 07 10:13:41: | Backtrace[1] 0xf7bfa6f8 eip 0x80c9fdb
Jul 07 10:13:41: | Backtrace[2] 0xf7bfac64 eip 0xf7f71400
Jul 07 10:13:41: | Backtrace[3] 0xf7bfad8c eip 0x483092
Jul 07 10:13:41: | Backtrace[4] 0xf7bfb2f8 eip 0x4bfdad
Jul 07 10:13:41: | Backtrace[5] 0xf7bfb318 eip 0x4bfed4
Jul 07 10:13:41: | Backtrace[6] 0xf7bfb33c eip 0x61ecaa
Jul 07 10:13:41: | Backtrace[7] 0xf7bfb354 eip 0x61ed4d
Jul 07 10:13:41: | Backtrace[8] 0xf7bfb370 eip 0x61c788
Jul 07 10:13:41: | Backtrace[9] 0xf7bfb378 eip 0x616850
Jul 07 10:13:41: | Backtrace[10] 0xf7bfb398 eip 0x81e378c
Jul 07 10:13:41: | Backtrace[11] 0xf7bfb498 eip 0x615935
Jul 07 10:13:41: | Backtrace[12] 00000000 eip 0x53482e
Jul 07 10:13:41: | Your core dump size limit is 51200 kb.
Jul 07 10:13:41: | Attempting to dump core ...
Jul 07 10:13:41: | VMServerd Panic: Exiting on unexpected signal.

I did a bit of research and found out that I needed the 32-bit version of libgcc (I already had the 64-bit version, but that was not sufficient).

Ran the following command:

yum install libgcc.i586

And now I am able to create new VMs.

Monday, July 6, 2009

VMware Server and Fedora Core 11, Part 3

I ended up recompiling the kernel by following the directions here step-by-step:

http://fedoraproject.org/wiki/Docs/CustomKernel

I applied the kernel patch that was included in: vmware-update-2.6.29-5.5.9-3.tar.bz2 and built new RPM packages.

However, when I went to install the new kernel, I ended up getting an error about a failed dependency on kernel-firmware.

I found this post: http://forums.fedoraforum.org/showthread.php?t=206844&highlight=kernel+rpm+failed+dependencies

and made the changes described to kernel.spec


%define with_firmware %{?_with_firmware: 1} %{?!_with_firmware: 0}
-----------to look like this-------------------
%define with_firmware %{?_with_firmware: 0} %{?!_with_firmware: 1}



%define with_firmware %{?_without_firmware: 0} %{?!_without_firmware: 1}
-----------to look like this-------------------
%define with_firmware %{?_without_firmware: 1} %{?!_without_firmware: 0}


And then re-recompiled the kernel.

This time, there was a kernel-firmware.*.rpm in my ~/rpmbuild/RPMS/x86_64 (here is a directory listing):

kernel-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-debug-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-debug-debuginfo-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-debug-devel-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-debuginfo-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-debuginfo-common-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-devel-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-firmware-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm
kernel-headers-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm

I ran the following command:

rpm -ivh kernel-firmware-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm kernel-headers-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm kernel-devel-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm kernel-2.6.29.5-191.pjt20090702.fc11.x86_64.rpm

And was able to get my custom kernel installed.

From here, I just followed the steps in my first post for getting through vmware-config.pl successfully (vmmon and vmnet compiled and all that good stuff).

Successful execution of VMware Server 1.0.9 and able to start up existing VMs.

Thursday, July 2, 2009

VMware Server and Fedora Core 11, Part 2

Well, after going through the steps described in my last post, I had a successful run of vmware-config.pl and was *finally* able to run the VMware Admin Console.

However, whenever I tried to Power On a VM, I would get a general error message. I turned on logging for one of the VMs and got the following:

Unable to change virtual machine power state: The process exited with an error:
vmxvmdb: Index name being generated from config file
POST(no connection): Version mismatch with vmmon module: expecting 138.0, got 208.0.
You have an incorrect version of the `vmmon' kernel module.
Try reinstalling VMware Server.

I'm pretty sure this is because of using the patch that modified the VM module source.

So, I'm stepping back and going through the painful process of running a patch against the Linux kernel source and recompiling the kernel, to get past the init_mm issue.

Recompiling the kernel takes forever, and something went wrong on my first attempt, so I am re-recompiling now...

Monday, June 29, 2009

VMware Server 1.0.9 Installation on Fedora Core 11 (Kernel: 2.6.29.5-191)

I recently installed Fedora Core 11 (x86_64) on my desktop and went about installing VMware Server.

Initially, I installed VMware Server 2.0.1. However, whenever I went to Power Off a VM, it would hang at 95%.

On occasion, it would also hang at 95% when I went to Power On a VM.

This issue has been discussed at length on VMware's discussion forum:
http://communities.vmware.com/thread/171066

However, I did not see an adequate solution.

Based on this bug and the odious new Web Admin console, I decided to drop back to VMware Server 1.0.9. I've always preferred the VMware Server 1.x client Admin console.

Here is a chronicle of my misadventures with installing VMware Server 1.0.9 on Fedora Core 11:

First attempt:

Downloaded / ran patch: vmware-update-2.6.29-5.5.9-3.tar.bz2

Error message received:

WARNING: "init_mm" [/tmp/vmware-config4/vmmon-only/vmmon.ko] undefined!
CC /tmp/vmware-config4/vmmon-only/vmmon.mod.o
LD [M] /tmp/vmware-config4/vmmon-only/vmmon.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.29.5-191.fc11.i686.PAE'
cp -f vmmon.ko ./../vmmon.o
make: Leaving directory `/tmp/vmware-config4/vmmon-only'

Unable to make a vmmon module that can be loaded in the running kernel:
insmod: error inserting '/tmp/vmware-config4/vmmon.o': -1 Unknown symbol in module
There is probably a slight difference in the kernel configuration between the set of C header files you specified and your running kernel. You may want to rebuild a kernel based on that directory, or specify another directory.

For more information on how to troubleshoot module-related problems, please visit our Web site at "http://www.vmware.com/download/modules/modules.html" and "http://www.vmware.com/support/reference/linux/prebuilt_modules_linux.html".

Execution aborted.


Key VMware Community Posts:
http://communities.vmware.com/message/933763
http://communities.vmware.com/thread/131154
http://fedoraproject.org/wiki/Docs/CustomKernel?highlight

Instead of attempting to modify CONFIG_UNUSED_SYMBOLS and recompile kernel, went down different path.

New Attempt:

Found discussion: http://communities.vmware.com/thread/205686

Downloaded: vmware-server-modules-2629.tar.gz, untarred to /usr/lib/vmware/modules/source

Error message received:

Configuring the VMware VmPerl Scripting API.

Can't locate ExtUtils/Embed.pm in @INC (@INC contains: /usr/local/lib64/perl5/site_perl/5.10.0/x86_64-linux-thread-multi /usr/local/lib/perl5/site_perl/5.10.0 /usr/lib64/perl5/vendor_perl/5.10.0/x86_64-linux-thread-multi /usr/lib/perl5/vendor_perl/5.10.0 /usr/lib/perl5/vendor_perl /usr/lib64/perl5/5.10.0/x86_64-linux-thread-multi /usr/lib/perl5/5.10.0 /usr/lib/perl5/site_perl .).

BEGIN failed--compilation aborted.

Use of uninitialized value $inc in substitution (s///) at /usr/bin/vmware-config.pl line 6775. Use of uninitialized value $inc in substitution (s///) at /usr/bin/vmware-config.pl line 6776. Use of uninitialized value $inc in substitution (s///) at /usr/bin/vmware-config.pl line 6776. Could not find necessary components to build the VMware VmPerl Scripting API.

Look in your Linux distribution to see if there is a perl-devel package.

Install that package if it exists and then re-run this installation program.



Solution:

yum install perl-ExtUtils-Embed.x86_64

The issue was resolved. Re-ran vmware-config.pl.

Error message received:


Generating SSL Server Certificate
Unable to get the last modification timestamp of the destination file

/etc/vmware/ssl/rui.key.

Execution aborted.

Solution:

touch /etc/vmware/ssl/rui.key
touch /etc/vmware/ssl/rui.crt

Error message received:


sh: /usr/lib/vmware/bin/vmware-vmx: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory


This occurred immediately before being prompted to enter serial number.

I found the following article: http://www.geekadmin.com/?p=38

1. yum install glibc.i686
2. yum install xorg-x11-libs.i386

The first command worked, the second one did not.

Re-ran vmware-confg.pl.

Got immediate warning:


The correct version of one or more libraries needed to run VMware Server may be
missing. This is the output of ldd /usr/bin/vmware:
linux-gate.so.1 => (0xf7f4b000)
libm.so.6 => /lib/libm.so.6 (0xf7f0b000)
libdl.so.2 => /lib/libdl.so.2 (0xf7f06000)
libpthread.so.0 => /lib/libpthread.so.0 (0xf7eeb000)
libX11.so.6 => not found
libXtst.so.6 => not found
libXext.so.6 => not found
libXt.so.6 => not found
libICE.so.6 => not found
libSM.so.6 => not found
libXrender.so.1 => not found
libz.so.1 => not found
libc.so.6 => /lib/libc.so.6 (0xf7d77000)
/lib/ld-linux.so.2 (0xf7f4c000)



It turned out that I needed to install 32-bit libraries (even though I have the 64-bit Fedora Core 11 install).

Solution: Ran the following command to get the 32-bit libraries for my FC11 install (will be different for other Linux distros):

yum install libX11.i586 libXtst.i586 libXext.i586 libXt.i586 libICE.i586 libSM.i586 libXrender.i586 libXi zlib.i586
(note: zlib was the tricky one, this is actually the libz.so).

Successful run of vmware-config.pl