How to remove index.php in Codeigniter URL

By default, the index.php file will be included in your URLs:

example.com/index.php/news/article/my_article

You can easily remove this file by using a .htaccess file with some simple rules. Here is an example of such a file, using the “negative” method in which everything is redirected except the specified items:


<code>RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]</code>

In the above example, any HTTP request other than those for index.php, images, and robots.txt is treated as a request for your index.php file.

Linq to SQL with WCF Services

I was interested to see how I could use Linq to SQL with WCF Services to load and save data using a Silverlight project.  In this post I will expand upon the database I created in my Linq to SQL Tutorial and the console application I wrote for my Set inheritance modifiers with SQLMetal post.

The first step is to enable serialisation on my Linq entities so that they can be sent over the wire. To do this in the O/R Designer you can select the white space of the designer and view the DataContext properties.  Set the property called Serialization Mode to Unidirectional:

Linq Serialization Mode Property

 

If using SQLMetal you can use the serialization command line argument:

1
SQLMetal.exe"/server:localhost /database:University /dbml:University.dbml <strong>/serialization:unidirectional</strong> /namespace:Entities /context:UniversityDataContext /pluralize

Enabling unidirectional serialization in either of these two ways adds the necessaryDataContract and DataMember attributes to the generated entities and properties:

1
2
3
4
5
6
7
8
9
10
11
12
13
[Table(Name="dbo.Student")]
[DataContract()]
public partial class Student : EntityBase, INotifyPropertyChanging, INotifyPropertyChanged
{
    ....
    [Column(Storage="_Forename", DbType="NVarChar(50) NOT NULL", CanBeNull=false, UpdateCheck=UpdateCheck.Never)]
    [DataMember(Order=3)]
    public string Forename
    {
        ....
    }
}

The entities are now in a state where they can be serialised and sent down the wire.  In my WCF service I have a method that returns a list of my Linq to SQL Student entity:

1
2
3
4
5
6
7
public List GetStudents()
{
    using (_context)
    {
        return _context.Students.ToList();
    }
}

These entities can then be easily used by the client, in this case the Silverlight application:

1
2
3
4
5
6
7
8
9
10
11
12
UniversityContractClient _proxy = new UniversityContractClient();
private void PopulateStudents()
{
    _proxy.GetStudentsCompleted += new EventHandler(proxy_GetStudentsCompleted);
    _proxy.GetStudentsAsync();
}
void proxy_GetStudentsCompleted(object sender, GetStudentsCompletedEventArgs e)
{
    dgStudents.ItemsSource = e.Result;
}

Here I am using the list to populate a DataGrid:

Linq WCF Datagrid

This is all very straight forward, but the next step to update the data it a little more complex.  Here is my service method to save a Student entity created or updated by the client:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void SaveStudent(Student student)
{
    using (_context)
    {
        if (student.IsNew)
        {
            _context.Students.InsertOnSubmit(student);
        }
        else
        {
            _context.Students.Attach(student, true);
        }
              
        _context.SubmitChanges();
    }
}

Here I am using the IsNew property I created in my Set inheritance modifiers with SQLMetalpost to check if the entity is to be inserted or updated.  The insert code is simple enough, but for the update we have to attach the entity to the DataContext as it has been modified outside of the DataContext’s scope.  I’m at doing this using the Attach method of the Student table, passing true for the asModified parameter to state that the entity has been updated.

In my Silverlight application I have a DataForm which calls this method passing the updated Student entity:

Linq WCF DataForm

At this point inserting data will work, but when I try to update an entity the service method will throw the following error when trying to attach the entity:

An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.

This occurs because the entity was modified outside of the scope of the DataContext, so Linq to SQL doesn’t know what has changed about the entity and what to update.  To overcome this we can use a Timestamp column.  The Timestamp is a byte array which is used for versioning.  Linq to SQL knows to check this column to see if an object has been updated.  In my database I have changed the Student table so that it has a field called Timestamp, of type timestamp which doesn’t allow NULLs:

Linq WCF Timestamp Field

When adding the new column, the O/R Designer automatically knows this is a timetamp column and sets the Time Stamp and Auto Generated Value properties to true:

Linq WCF Timestamp Properties

 

SQLMetal will also detect a column with the timestamp type and set the necessary attributes.

With this timestamp column set up it will now be possible to successfully update an entity that was changed by the client.

In my example if I try to update the entity twice it will throw the following exception when trying to submit the changes:

Row not found or changed.

This is because the client doesn’t have the entity with the updated timestamp.  Also when adding a new entity the entity at the client won’t have the updated ID identity column so trying to update this will create another entity.  To resolve this I can change my SaveStudent service method to return the updated Student entity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public Student SaveStudent(Student student)
{
    using (_context)
    {
        if (student.IsNew)
        {
            _context.Students.InsertOnSubmit(student);
        }
        else
        {
            _context.Students.Attach(student, true);
        }
              
        _context.SubmitChanges();
    }
    return student;
}

In my Silverlight application I then pass the hash code for the object as the userState when calling the asyncronus service method:

1
_proxy.SaveStudentAsync(student, student.GetHashCode());

This user state can then be obtained in the callback EventArgs class using e.UserState.  Using this I get the correct object from my collection, update it and reassign the source for my DataGrid and DataForm:

1
2
3
4
5
6
7
8
9
10
11
12
void _proxy_SaveStudentCompleted(object sender, SaveStudentCompletedEventArgs e)
{
    ObservableCollection students = (ObservableCollection)dgStudents.ItemsSource;
    Student student = students.Where(s => s.GetHashCode() == Convert.ToInt32(e.UserState)).First();
    if (student.ID == 0)
    {
        student.ID = e.Result.ID;
    }
    student.Timestamp = e.Result.Timestamp;
    dgStudents.ItemsSource = students;
    dfStudent.ItemsSource = students;
}

This is all well and good and works as expected but what I really wanted to do was have an UpdateDate column which holds the date of the last update which could be used as a timestamp.  I replaced my current Timestamp column with an UpdateDate column:

Linq WCF UpdateDate Field

The default for the new column is set to getdate() to automatically populate with the current date when creating a new record:

Linq WCF UpdateDate Default

Using the O/R Designer this field can be set to a timestamp by setting the Time Stamp property to True, which will automatically set Auto Generated Value to True.

As I am using SQLMetal I can update the console application I wrote in my Set inheritance modifiers with SQLMetal post to add an IsVersion attribute to the DBML XML as well as the Modifier attribute:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.... code omitted ....
//Find the column node
if (child.Name.Equals("Column"))
{
    if (child.Attributes["Name"].Value.Equals("ID"))
    {
        //Create the Modifier attribute to add to ID column
        XmlAttribute modifierAttribute = xmlDoc.CreateAttribute("Modifier");
        modifierAttribute.Value = "Override";
        child.Attributes.Append(modifierAttribute);
    }
    else if (child.Attributes["Name"].Value.Equals("UpdateDate"))
    {
        //Create the IsVersion attribute to add to UpdateDate column
        XmlAttribute versionAttribute = xmlDoc.CreateAttribute("IsVersion");
        versionAttribute.Value = "True";
        child.Attributes.Append(versionAttribute);
    }
}
.... code omitted ....

Doing this adds the following values to the Column attribute on the UpdateDate property in the Student entity.  You can see IsVersion=true which tells Linq to SQL this property is the timestamp.

1
[Column(Storage="_UpdateDate", AutoSync=AutoSync.Always, DbType="DateTime NOT NULL", IsDbGenerated=true, IsVersion=true, UpdateCheck=UpdateCheck.Never)]

At this point everything works okay, but the UpdateDate is not refreshed on update.  To fix this add a trigger that sets the date on update:

1
2
3
4
5
6
7
ALTER TRIGGER trg_UpdateDate
ON dbo.Student
FOR UPDATE
AS
    UPDATE      Student
    SET         UpdateDate = getdate()
    WHERE       (ID IN (SELECT ID FROM Inserted))

The UpdateDate is now set for each update and is used by Linq to SQL as the timestamp.

Referenced by: http://www.joe-stevens.com/2009/07/10/linq-to-sql-with-wcf-services/

How to call a WCF service using ksoap2 on android

In “theory” wcf with basic http binding and asmx should work the same.

It could be something to do with how your WCF service is configured.

We get a similar problem if we configure TransferMode Streamed on the client and Buffered on the server. Although not sure if this is relevant in your case.

 
private static final String SOAP_ACTION = "http://tempuri.org/IContact/GetContactCount"; 
private static final String METHOD_NAME = "GetContactCount"; private static final String NAMESPACE = "http://tempuri.org/"; 
private static final String URL = "http://xxx.xxx.com/Contacts/ContactsService.Contacts.svc";

import org.ksoap2.*;
import org.ksoap2.serialization.*;
import org.ksoap2.transport.*;
import org.xmlpull.v1.XmlSerializer;

import android.app.Activity;
import android.os.Bundle;
import android.util.Xml;
import android.widget.TextView;

public class ksop2test extends Activity {
/** Called when the activity is first created. */

private static final String METHOD_NAME = "HelloWorldRequest";
//  private static final String METHOD_NAME = "HelloWorld";

private static final String NAMESPACE = "http://tempuri.org/";
//  private static final String NAMESPACE = "http://tempuri.org";

private static final String URL = "http://192.168.0.2:8080/HelloWCF/Service1.svc";
//  private static final String URL = "http://192.168.0.2:8080/webservice1  /Service1.asmx";

final String SOAP_ACTION = "http://tempuri.org/IService1/HelloWorld";
//  final String SOAP_ACTION = "http://tempuri.org/HelloWorld";
TextView tv;
StringBuilder sb;
private XmlSerializer writer;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
sb = new StringBuilder();
call();
tv.setText(sb.toString());
setContentView(tv);
}

public void call() {
try {

SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

request.addProperty("Name", "Qing");

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);

HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapPrimitive result = (SoapPrimitive)envelope.getResponse();

//to get the data
String resultData = result.toString();
// 0 is the first object of data

sb.append(resultData + "\n");
} catch (Exception e) {
sb.append("Error:\n" + e.getMessage() + "\n");
}

}

}

Referenced by: http://stackoverflow.com/questions/2589486/how-to-call-a-wcf-service-using-ksoap2-on-android

Communication Between WCF Service and Android Client

Communication Between WCF Service and Android Client

Overview of REST in WCF
Windows Communication Foundation (WCF), part of the .NET Framework, provides the first unified programming model for rapidly building service-oriented applications. It enables the development of secure, reliable, transacted services that interoperate with current Microsoft investments and non-Microsoft platforms.

With the .NET Framework 3.5 release, WCF added support for building REST style services. REST, an architectural style for building distributed hypermedia driven applications, involves building resource-oriented services by defining resources that implement uniform interfaces using standard HTTP verbs (GET, POST, PUT, and DELETE), and that can be located/identified by a URI.

REST support within WCF was enhanced with the release of .NET Framework 3.5 SP1 to add make REST development easier and to support the ADO.NET Entity Framework entities in WCF contracts. Improvements were made around UriTemplate flexibility and the Visual Studio tooling to increase developer productivity.

Code example

A good tutorial on how to create RESTful Service using Visual Studio can be found here.

First we need to define the structure (class) which will be used for data exchange between server and client. In this case I created a base class named Response and extended classes named ActivityStatusResponse and ConnectionStatusResponse:

    public class Response
    {
        private bool successful;
        private string comment;

        public bool Successful
        {
            get
            {
                return successful;
            }
            set
            {
                successful = value;
            }
        }

        public string Comment
        {
            get
            {
                return comment;
            }
            set
            {
                comment = value;
            }
        }
    }

    public class ActivityStatusResponse : Response
    {
        private string activity;

        public string Activity
        {
            get
            {
                return activity;
            }
            set
            {
                activity = value;
            }
        }
    }

Next we need to define the methods, message formats and URI templates in the interface:

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/{strSessionString}/activityStatus")]
ActivityStatusResponse GetActivityStatus(string strSessionString);[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/{strSessionString}/time={time}&lat={latitude}&long={longitude}")]
Response StoreLocation(string strSessionString, string time, string latitude, string longitude);

WebMessageFormat parameter defines the data exchange format. In this example JSON format is used.

UriTemplate parameter defines the URI template.

The parameters within curly braces represent variable values. Everything else in the URI (not enclosed within curly braces) is considered a static part of the URI.

After the definition we have to implement the methods. The following code shows the implementation of StoreAcceleration method:

public Response StoreAcceleration(string strSessionString, string strMeasurementTime, string strAccelerationX, string strAccelerationY, string strAccelerationZ)
        {
            SQLWorks sqlWorks = new SQLWorks();
            Response response = new Response();
            try
            {
                string strTime = strMeasurementTime.Replace("_", " ");
                DateTime measurementTime = DateTime.ParseExact(strTime, "yyyy-MM-dd HH:mm:ss:fff", null);
                double accelerationX = Convert.ToDouble(strAccelerationX.Replace(".", ","));
                double accelerationY = Convert.ToDouble(strAccelerationY.Replace(".", ","));
                double accelerationZ = Convert.ToDouble(strAccelerationZ.Replace(".", ","));

                sqlWorks.StoreAcceleration(strSessionString, measurementTime, accelerationX, accelerationY, accelerationZ);

                response.Successful = true;
                response.Comment = "Stored!";
            }
            catch(Exception ex)
            {
                string sDummy = ex.ToString();
                response.Comment = "an error occured!";
                response.Successful = false;
            }

            return response;
        }

The service Endpoint and other properties are defined in .config file:

<configuration>
<system.web>
<compilation debug=”true”>
</compilation>
<system.servicemodel>
<bindings>
<webhttpbinding>
<binding name=”DefaultBinding”>
</binding>
</webhttpbinding>
<behaviors>
<endpointbehaviors>
<behavior name=”RESTFriendly”>
<webhttp>
</webhttp>
<behavior name=”RESTServer.JsonServiceAspNetAjaxBehavior”>
<enablewebscript>
</enablewebscript>
</behavior>
<servicebehaviors>
<behavior name=”RESTFriendly”>
<servicemetadata httpgetenabled=”true”>
<servicedebug includeexceptiondetailinfaults=”false”>
</servicedebug>
</servicemetadata>
</behavior>
<services>
<service name=”RESTServer.GaitLinkService”>
<endpoint address=”" behaviorconfiguration=”RESTFriendly” binding=”webHttpBinding” bindingconfiguration=”DefaultBinding” contract=”RESTServer.IGaitLinkService”>
<identity>
<dns value=”localhost”>
</dns>
</identity>
</endpoint>
</service>
<servicehostingenvironment aspnetcompatibilityenabled=”true”>
</servicehostingenvironment>
</services></servicebehaviors></behavior></endpointbehaviors></behaviors></bindings></system.servicemodel></system.web></configuration>

At this point everything is ready to host the service in the windows application:

public void StartRestService()
        {
            try
            {
                WebHttpBinding binding = new WebHttpBinding();
                RESTServiceHost = new ServiceHost(typeof(GaitLinkService), new Uri("http://localhost:8000/GaitLink"));
                RESTServiceHost.AddServiceEndpoint(typeof(IGaitLinkService), binding, "GaitLink");
                RESTServiceHost.Open();
            }
            catch(Exception ex)
            {
                string sDummy = ex.ToString();
                //TODO: notify user about the error!
            }
        }

Client application

On client side there is a service called CommunicationService and additional class RestClient. Function arguments are sent to the server by generating the url address which has to be the same format as the template specified in the service interface on the server side.

Class RestClient.java:

package com.client.gaitlink;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class RestClient {

	private static String loginParameters;
	private static String accelerationParameters;
	private static String activityRequestParameters;
	private static String locationParameters;
	private static String serviceAddress = "http://76.30.178.213:8000/GaitLink/";

	private static String convertStreamToString(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}

	public static void connect(String url) {

		HttpClient httpclient = new DefaultHttpClient();

		HttpGet httpget = new HttpGet(url);

		//HttpPost httppost = new HttpPost(url);

		HttpResponse response;
		try {

			response = httpclient.execute(httpget);

			Log.i("REST:Response Status line", response.getStatusLine().toString());

			HttpEntity entity = response.getEntity();

			if (entity != null) {

				InputStream instream = entity.getContent();
				String result = convertStreamToString(instream);
				Log.i("REST: result", result);

				JSONObject json = new JSONObject(result);
				Log.i("REST", "<jsonobject>\n" + json.toString()
						+ "\n</jsonobject>");

				// Parsing
				JSONArray nameArray = json.names();
				JSONArray valArray = json.toJSONArray(nameArray);
				for (int i = 0; i < valArray.length(); i++) {
					Log
							.i("REST", "<jsonname" + i + ">\n"
									+ nameArray.getString(i) + "\n</jsonname"
									+ i + ">\n" + "<jsonvalue" + i + ">\n"
									+ valArray.getString(i) + "\n</jsonvalue"
									+ i + ">");
				}

				json.put("sample key", "sample value");
				Log.i("REST", "<jsonobject>\n" + json.toString()
						+ "\n</jsonobject>");

				instream.close();
			}

		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public class Response
	{
		public boolean isSuccessful() {
			return successful;
		}

		public void setSuccessful(boolean successful) {
			this.successful = successful;
		}

		public String getComment() {
			return comment;
		}

		public void setComment(String comment) {
			this.comment = comment;
		}

		private boolean successful;
		private String comment;

		public Response()
		{
			this(false, null);
		}

		public Response(boolean successful, String comment)
		{
			this.successful = successful;
			this.comment = comment;
		}
	}

	public class LoginResponse extends Response
	{
		private String strSessionString;

		public LoginResponse()
		{
			this(false, null, "LoginFailed");
		}

		public LoginResponse(boolean successful, String strSessionString, String comment)
		{
			super(successful, comment);
			this.strSessionString = strSessionString;
		}

		public String getStrSessionString() {
			return strSessionString;
		}

		public void setStrSessionString(String strSessionString) {
			this.strSessionString = strSessionString;
		}
	}

	public class ActivityStatusResponse extends Response
	{
		private String activity;

		public String getActivity() {
			return activity;
		}

		public void setActivity(String activity) {
			this.activity = activity;
		}

		public ActivityStatusResponse(boolean successfull, String activity, String comment)
		{
			super(successfull, comment);
			this.activity = activity;
		}

		public ActivityStatusResponse()
		{
			this(false, null, "activity request failed");
		}
	}

	private static void SetLoginParameters(String username, String password)
	{
		loginParameters = "Login?username=" + username + "&password=" + password;
	}

	public LoginResponse Login(String username, String password)
	{
		SetLoginParameters(username, password);

		HttpClient httpclient = new DefaultHttpClient();
		HttpGet httpget = new HttpGet(serviceAddress + loginParameters);

		HttpResponse response;

		LoginResponse loginResponse = null;

		try
		{
			response = httpclient.execute(httpget);

			HttpEntity entity = response.getEntity();

			if(entity != null)
			{
				InputStream instream = entity.getContent();
				String result = convertStreamToString(instream);
				JSONObject json = new JSONObject(result);

				// Parsing
				JSONArray nameArray = json.names();
				JSONArray valArray = json.toJSONArray(nameArray);

				loginResponse = new LoginResponse(valArray.getBoolean(1), valArray.getString(0), valArray.getString(2));

				instream.close();
			}

		}
		catch(Exception e)
		{
			loginResponse = new LoginResponse();
			String sDummy = e.toString();
		}
		return loginResponse;
	}

	public Response SendAccelerations(String sSession, String measurementTime, double ax, double ay, double az)
	{
		setAccelerationParameters(sSession, measurementTime, ax, ay, az);

		HttpClient httpclient = new DefaultHttpClient();
		HttpGet httpget = new HttpGet(serviceAddress + accelerationParameters);

		HttpResponse response;

		Response accelerationResponse = null;

		try
		{
			response = httpclient.execute(httpget);

			HttpEntity entity = response.getEntity();

			if(entity != null)
			{
				InputStream instream = entity.getContent();
				String result = convertStreamToString(instream);
				JSONObject json = new JSONObject(result);

				// Parsing
				JSONArray nameArray = json.names();
				JSONArray valArray = json.toJSONArray(nameArray);

				accelerationResponse = new Response(valArray.getBoolean(0), valArray.getString(1));

				instream.close();
			}

		}
		catch(Exception e)
		{
			accelerationResponse = new Response();
			String sDummy = e.toString();
		}
		return accelerationResponse;
	}

	private static void setAccelerationParameters(String sSession, String measurementTime, double ax, double ay, double az)
	{
		accelerationParameters = sSession + "/measurementTime=" + measurementTime + "&accelerationX=" + ax + "&accelerationY=" + ay + "&accelerationZ=" + az;
		accelerationParameters = accelerationParameters.replaceAll(" ", "_");
	}

	public Response SendLocation(String sSession, String locationTime, double latitude, double longitude)
	{
		setLocationParameters(sSession, locationTime, latitude, longitude);

		HttpClient httpclient = new DefaultHttpClient();
		HttpGet httpget = new HttpGet(serviceAddress + locationParameters);

		HttpResponse response;

		Response locationResponse = null;

		try
		{
			response = httpclient.execute(httpget);

			HttpEntity entity = response.getEntity();

			if(entity != null)
			{
				InputStream instream = entity.getContent();
				String result = convertStreamToString(instream);
				JSONObject json = new JSONObject(result);

				// Parsing
				JSONArray nameArray = json.names();
				JSONArray valArray = json.toJSONArray(nameArray);

				locationResponse = new Response(valArray.getBoolean(0), valArray.getString(1));

				instream.close();
			}

		}
		catch(Exception e)
		{
			locationResponse = new Response();
			String sDummy = e.toString();
		}
		return locationResponse;
	}

	private static void setLocationParameters(String sSession, String locationTime, double latitude, double longitude)
	{
		///{strSessionString}/time={time}&lat={latitude}&long={longitude}
		locationParameters = sSession + "/time=" + locationTime + "&lat=" + latitude + "&long=" + longitude;
		locationParameters = locationParameters.replaceAll(" ", "_");
	}

	public ActivityStatusResponse GetActivity(String sSession)
	{
		setActivityRequestParameters(sSession);

		HttpClient httpclient = new DefaultHttpClient();
		HttpGet httpget = new HttpGet(serviceAddress + activityRequestParameters);

		HttpResponse response;

		ActivityStatusResponse activityStatusResponse = null;

		try
		{
			response = httpclient.execute(httpget);

			HttpEntity entity = response.getEntity();

			if(entity != null)
			{
				InputStream instream = entity.getContent();
				String result = convertStreamToString(instream);
				JSONObject json = new JSONObject(result);

				// Parsing
				JSONArray nameArray = json.names();
				JSONArray valArray = json.toJSONArray(nameArray);

				activityStatusResponse = new ActivityStatusResponse(valArray.getBoolean(0), valArray.getString(1), valArray.getString(2));

				instream.close();
			}

		}
		catch(Exception e)
		{
			activityStatusResponse = new ActivityStatusResponse();
			String sDummy = e.toString();
		}
		return activityStatusResponse;
	}

	private static void setActivityRequestParameters(String sSession)
	{
		activityRequestParameters = "/" + sSession + "/activityStatus";
	}
}</pre>
</div>
<div>

RestClient methods are called from CommunicationService class. The following example shows the method which retrieves the activity status:

</div>
<div>
<pre id="bt_plainText">private void requestActivity()
	{
		try
		{
			if(strSessionString != null)
			{
				ActivityStatusResponse response = restClient.GetActivity(strSessionString);
				connectionAvailable = response.isSuccessful();
				strActivity = response.getActivity();
				if(strActivity != null && strActivity != "")
				{
					announceActivityStatus();
				}

			}
		}
		catch(Exception e)
		{
			connectionAvailable = false;
		}
	}

The example above is just a brief overview of practical RESTful service realization using WCF and data exchange with Android client. More detailed explanations of each segment could be found at the given addresses.
References

A Guide to Designing and Building RESTful Web Services with WCF 3.5
Windows Communication Foundation Architecture
What Is Windows Communication Foundation?

Getting Started Building a WCF Web Service

This post is the first in a series of upcoming MSDN articles on creating a claims-aware web service and consuming it from SharePoint BCS.  In the short time that I’ve worked with claims-based authentication, what I experience is that while there are not very many steps to get it working, if you get anything wrong, then it just doesn’t work, and it takes some effort to figure out the problem.  My approach in these articles is to supply some procedures with small steps, with instructions all along the way to validate that what you have done so far works properly.  So the first step is to create a WCF web service, host it using IIS, and validate that it is working.

Getting Started Building a WCF Web Service
(This post)
Shows how to create a very simple web service using WCF.  Shows how to host this web service using IIS.
Determining Caller Identity within a WCF Web Service Enhances the example so that the Web service can authoritatively report on the identity of its caller.
Establishing Trust between a WCF Web Service and the SharePoint 2010 Security Token Service Configures the example developed in the previous article so that it uses a self-signed certificate to support a secure connection.
Consuming a Claims-Enabled WCF Web Service as an SharePoint 2010 External Content Type Walks through the procedure for consuming a claims-enabled web service as a SharePoint 2010 External Content Type.

These articles were written by Saji Varkey, and Bin Zhang, and me.  They will be published on MSDN sometime in the near future.  After they are published, I will update these posts to point to the MSDN articles.  Juan Balmori Labra was the program manager behind these articles.

This post shows how to create a very simple web service using Windows Communications Foundation (WCF).  There is one special characteristic of the web service that I present in this article, which is that while it is very simple, it can be consumed as an External Content Type (ECT) from Business Connectivity Services (BCS).  In addition, the procedure presented in this post shows how to host this web service using Internet Information Services (IIS).

This web service contains only two methods: a ‘finder’ to retrieve a collection of items, and a ‘specific finder’ to retrieve a single item.  The ‘database’ behind the collection is just an initialized list.  The ‘schema’ of this little ‘database’ is very simple.  It is a single flat table consisting of two fields – an integer CustomerID, and a stringCustomerName.  CustomerID is a unique ID.

return new List<Customer>()
{
new Customer
{
CustomerID = 1,
CustomerName = ”Bob”,
},
new Customer
{
CustomerID = 2,
CustomerName = ”Bill”,
},
new Customer
{
CustomerID = 3,
CustomerName = ”Cheryl”,
},
};

After building and configuring this web service, you can use SharePoint Designer 2010 to create an ECT from it, and then view the data in a SharePoint list.

 

As you probably know, BCS in SharePoint server 2010 is read/write.  If you supply additional methods to create, update, and delete items, then you can fully maintain the data in a list.  I’m interested in keeping this web service absolutely as simple as possible, so this is only a read-only implementation.  My focus will be completely on the security and identity issues.  How the database is stored, where it is stored, or the details of the schema are irrelevant to the topic at hand.

The procedure presented here is for Windows Server 2008 R2 and Windows Server 2008.  You can build this web service using either Visual Studio 2010 or Visual Studio 2008.

You can build, run, and test the web service presented in this post on any development computer that is running IIS.  However, if you want to connect to this web service as an ECT using BCS, then build this example on a SharePoint 2010 development machine, so that the SharePoint 2010 server and the example web service are running on the same computer.  You can put this web service on a different machine, and consume it as an ECT, however, in that situation, you must either remove security, or you need to create a claims-aware web service.

As I mentioned, the procedure that I present here shows how to host the web service under IIS.  This is the way that most implementers of such a web service will want to host it.  Hosting it as a service of IIS gives lots of benefits such as process recycling, process health monitoring, and message based activation.

Building the Example

This procedure is for Windows Server 2008 or Windows Server 2008 R2.  In both cases, I started on a machine that had a fresh, patched install of the operating system.  I then installed the necessary roles and features so that Internet Information Services (IIS) was installed and running.  In addition, the procedures presented in this post require the .NET Framework 3.5.1, and either Visual Studio 2008 or Visual Studio 2010.

Installing WCF and IIS

Use Server Manager to install the Web Server (IIS) Role and the.NET Framework 3.5.1 feature.

To run this example, the only Role that is required is Web Server (IIS).

 

After adding the Web Server (IIS) role, the Roles wizard will ask you to select Role Services.  Select Application Development.

 

To install the .NET Framework, add the .NET Framework 3.5.1 Features.

 

When you are installing this feature on Windows Server 2008 (not R2), after selecting the .NET Framework 3.0 Features, select WCF Activation.  This is selected by default on Windows Server 2008 R2.

 

Both WCF and IIS must be installed for IIS-hosted WCF services to function correctly.  The procedures for installing WCF (as part of the .NET Framework 3.0) and IIS vary depending on the operating system that you are using.  If you are installing on an operating system other than Windows Server 2008 or Windows Server 2008 R2, seeMicrosoft .NET Framework 3.0 Redistributable Package to download and install the .NET Framework 3.0.  SeeInstalling IIS for further instructions in that area.

Registering the Service Model

To run this example, you need to register this version of WCF and update scriptmaps at the IIS metabase root.

1.       Start a Visual Studio Command Prompt.  Run as administrator.

 

Click Start => All Programs => Visual Studio 2010 => Visual Studio Tools => Visual Studio Command PromptRight-click, select Start as Administrator.

The Visual Studio command prompt is located in a similar place for Visual Studio 2008.

2.       Change directory to:

c:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation

Enter:

cd “c:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation”

3.       In the command prompt, enter:

ServiceModelReg -i

 

This didn’t need to be a Visual Studio command prompt, but the following step needs a Visual Studio command prompt, so for efficiency, I created one in this step.

Updating Script Maps

4.       In the command prompt, enter:

aspnet_regiis.exe -i

 

Creating a Web Service

1.       Create a directory, C:\MyWebService, which will contain the web service.  If you use a different directory than this, you will need to alter these procedures as appropriate.

2.       Start Visual Studio 2010 (or 2008).

3.       Click File => New => Project.

a.       For the installed template category, select WCF.

b.      For the template, select WCF Service Application.

c.       Target the .NET Framework 3.5.

d.      For the location of the project, browse to the directory that you created in step 1.

e.      Name the project CustomersService.

f.        Do not create a directory for the solution.

 

Note: Don’t forget to target the .NET Framework 3.5.  By default, Visual Studio will target the .NET Framework 4.0, and you must change to 3.5 for the procedure presented here to work.

4.       In the project, rename IService1.cs to ICustomers.cs.  Visual Studio 2010 will ask whether you would also like to perform a rename in this project of all references to the code element ‘IService1’?  Click Yes.  Actually, we’re going to replace all code in all modules, so it doesn’t matter whether you click Yes or No.

5.       In the project, rename Service1.svc to Customers.svc.  After renaming these items, the Solution Explorer will look like this.

6.       Replace Customers.svc with the following single line of markup.  Right click on Customers.svc, and selectView Markup.  Copy, paste, and save.
<%@ ServiceHost Language=”C#” Debug=”true” Service=”CustomersService.Customers”CodeBehind=”Customers.svc.cs” %>
7.       Replace Customers.svc.cs with the following code.

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

namespace CustomersService
{
public class Customers : ICustomers
{
// Finder
public List<Customer> GetAllCustomers()
{
return new List<Customer>()
{
new Customer
{
CustomerID = 1,
CustomerName = ”Bob”,
},
new Customer
{
CustomerID = 2,
CustomerName = ”Bill”,
},
new Customer
{
CustomerID = 3,
CustomerName = ”Cheryl”,
},
};
}

// Specific finder
public Customer GetCustomerByID(int CustomerID)
{
return GetAllCustomers().FirstOrDefault(c => c.CustomerID == CustomerID);
}
}
}

8.       Replace ICustomers.cs with the following code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace CustomersService
{
[ServiceContract]
public interface ICustomers
{
[OperationContract] //finder
List<Customer> GetAllCustomers();

[OperationContract] //specificFinder
Customer GetCustomerByID(int CustomerID);
}

[DataContract]
public class Customer
{
[DataMember]
public int CustomerID { get; set; }

[DataMember]
public string CustomerName { get; set; }
}
}

9.       Replace Web.config with the following markup.  In Solution Explorer, right-click on Web.config and selectEdit.  Copy, paste, and save.  Important note: this is the Web.config that configures this specific web service.  It resides at C:\MyWebService\CustomersService.

<?xml version=”1.0″?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration=”CustomersService.Service1Behavior”
name=”CustomersService.Customers”>
<endpoint address=”" binding=”wsHttpBinding” contract=”CustomersService.ICustomers”>
<identity>
<dns value=”localhost” />
</identity>
</endpoint>
<endpoint address=”mex” binding=”mexHttpBinding” contract=”IMetadataExchange” />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name=”CustomersService.Service1Behavior”>
<!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
<serviceMetadata httpGetEnabled=”true”/>
<!– To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information –>
<serviceDebug includeExceptionDetailInFaults=”false”/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

10.   Build the application.

11.   Add an application to the default web site.

a.       Start Internet Information Services (IIS) Manager.  Click Start => All Programs => Administrative Tools =>Internet Information Services (IIS) Manager.

b.      In Internet Information Services (IIS) Manager, expand Sites, and right-click on Default Web Site, and selectAdd Application.

 

 

c.       In the Add Application dialog box, in the Alias field, enter Customers.  In the Physical Path field, browse toC:\MyWebService\CustomersService.  Click OK twice.

 

12.   Validate that the web service is running.  Start Internet Explorer, and browse tohttp://localhost/Customers/Customers.svc.  If the web service is running, you will see the following:

 

Another interesting approach to testing the Web service is to use the WCF test client.  Start a Visual Studio command prompt (or use the one that is open from the beginning of this procedure).  Enter wcftestclient to run the WCF test client.  Click File => Add Service.  Enter http://localhost/Customers/Customers.svc as the endpoint address, and click OK.

 

If the service was added successfully, you will see the methods that the service exposes.

 

Double-click on GetAllCustomers.  This opens a window that allows you to configure the request and invoke the request.  Click on Invoke to see the response from the Web service.

 

In the next article, we will add some Windows Identity Framework (WIF) features, which we can use to determine the identity of the caller.

 

Referenced by: http://blogs.msdn.com/b/ericwhite/archive/2010/05/11/getting-started-building-a-wcf-web-service.aspx

Catch scroll to end of DataGridView in C#

How to catch when the user scrolls to the bottom of the dataGridView, so I can load more results:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication30
{

    public partial class Form1 : Form
    {

        private DateTime lastLoading;
        private int firstVisibleRow;
        private ScrollBars gridScrollBars;

        public Form1()
        {
            InitializeComponent();

            //attach scroll event.
            dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

            //load firs 100 rows.
            LoadRows();
        }

        private void HideScrollBars()
        {
            gridScrollBars = dataGridView1.ScrollBars;
            dataGridView1.ScrollBars = ScrollBars.None;
        }

        private void ShowScrollBars()
        {
            dataGridView1.ScrollBars = gridScrollBars;
        }

        private int GetDisplayedRowsCount()
        {
            int count = dataGridView1.Rows[dataGridView1.FirstDisplayedScrollingRowIndex].Height;
            count = dataGridView1.Height / count;
            return count;
        }

        private void LoadRows()
        {
            HideScrollBars();

            System.Diagnostics.Debug.WriteLine("Load data");
            lastLoading = DateTime.Now;

            //create rows
            for (int i = 0; i < 100; i++)
            {
                int n =dataGridView1.Rows.Add();
                dataGridView1.Rows[n].Cells[0].Value = "Row - " + n.ToString();
            }

            //reset displayed row
            if (firstVisibleRow > -1)
            {
                ShowScrollBars();
                dataGridView1.FirstDisplayedScrollingRowIndex = firstVisibleRow;
            }
        }

        void dataGridView1_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.Type == ScrollEventType.SmallIncrement || e.Type == ScrollEventType.LargeIncrement)
            {
                if (e.NewValue >= dataGridView1.Rows.Count - GetDisplayedRowsCount())
                {
                    //prevent loading from autoscroll.
                    TimeSpan ts = DateTime.Now - lastLoading;
                    if (ts.TotalMilliseconds > 100)
                    {
                        firstVisibleRow = e.NewValue;
                        LoadRows();
                    }
                    else
                    {
                        dataGridView1.FirstDisplayedScrollingRowIndex = e.OldValue;
                    }
                }
            }
        }
    }
}
private DateTime lastLoading;

In this variable I save last loading time and it is used to prevent “loading while loading” (scroll event is fired while loading because of the automatic scrolling) . Interval between loading in this example is 100 ms.

  private int firstVisibleRow;

In this variable I save first visible row index before loading and set datagridview first visible row after loading. This is also used because of the automatic scrolling.

        private ScrollBars gridScrollBars;

In this variable I save datagridview scrollbars property and it is used to force scrollbar update because scrollbar is not updated after loading.

   //attach scroll event.
            dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

In this line I just atach datagridview scroll event.

            //load firs 100 rows.
            LoadRows();

In this line I load first 100 rows on startup. I use this method because in my test application I don’t have any data and this simulate real loading.

        private void HideScrollBars()
        {
            gridScrollBars = dataGridView1.ScrollBars;
            dataGridView1.ScrollBars = ScrollBars.None;
        }

In this method I save datagridview scrollbars in variable and hide scrollbars. (update scrollbars after loading).

    private void ShowScrollBars()
        {
            dataGridView1.ScrollBars = gridScrollBars;
        }

In this method I show datagridview scrollbars. (update scrollbars after loading).

        private int GetDisplayedRowsCount()
        {
            int count = dataGridView1.Rows[dataGridView1.FirstDisplayedScrollingRowIndex].Height;
            count = dataGridView1.Height / count;
            return count;
        }

In this method I calculate number of visible rows. This is needed because value in datagridview scroll event (e.NewValue) is index of first visible row in datagridview.

        private void LoadRows()
        {
            HideScrollBars();

            System.Diagnostics.Debug.WriteLine("Load data");
            lastLoading = DateTime.Now;

            //create rows
            for (int i = 0; i < 100; i++)
            {
                int n =dataGridView1.Rows.Add();
                dataGridView1.Rows[n].Cells[0].Value = "Row - " + n.ToString();
            }

            //reset displayed row
            if (firstVisibleRow > -1)
            {
                ShowScrollBars();
                dataGridView1.FirstDisplayedScrollingRowIndex = firstVisibleRow;
            }
        }

In this method I create rows in grid and you should replace for loop with your load data. You need code which is before and after loop.

    void dataGridView1_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.Type == ScrollEventType.SmallIncrement || e.Type == ScrollEventType.LargeIncrement)
            {
                if (e.NewValue >= dataGridView1.Rows.Count - GetDisplayedRowsCount())
                {
                    //prevent loading from autoscroll.
                    TimeSpan ts = DateTime.Now - lastLoading;
                    if (ts.TotalMilliseconds > 100)
                    {
                        firstVisibleRow = e.NewValue;
                        LoadRows();
                    }
                    else
                    {
                        dataGridView1.FirstDisplayedScrollingRowIndex = e.OldValue;
                    }
                }
            }

In this event handler I do few thing:

- Check scroll event type – because we need to load data only in scroll down

- Get new value from event args (e.NewValue) – this is index of first displayed row in grid

- Get displayed rows count – rows in view

- Check if new value is bigger or equal to last row in grid – if yes.. then load more data

- Check last loading time – prevent “loading from loading” (workaround for grid autoscroll)

Referenced by: http://social.msdn.microsoft.com/Forums/en-SG/Vsexpressvcs/thread/4a882eff-f6dd-4d8f-86d9-e3d85947522e

Set Up VPN for Mac

Mac OS X 10.5 (Leopard)

  1. Open System Preferences by going to Apple > System Preferences.Select System Preferences drop down menu
  2. Select the Network icon in the System Preferences window.Select Network icon
  3. Select the + button at the bottom left of the screen to add a new connection.Network window
  4. Select the following:
    a. Interface: VPN
    b. VPN Type: PPTP
    c. Service Name: NUVPN
    d. Select Create.Select interface window
  5. Click the arrows to the right Configuration and select Add Configuration from the drop down menu.Configuration drop down menu
  6. Enter NUVPN in the Name field and select Create.Name the configuration
  7. From Network window enter the following information:
    a. Server Address: vpn-public.vpn.northwestern.edu.
    b. Account Name: enter your NetIDc. (Optional) Check the Show VPN status menu bar box if you would like to start the VPN connection from your menu bar, otherwise you will need to openSystem Preferences.Network window
  8. Click the Advanced button.
  9. Select OptionsVerify Send all traffic over VPN connection is checked.Advanced
  10. Click the OK button.
  11. Click the Apply button.Network window
  12. Click the Connect button.

Support Contacts

How to create a setup project for a Windows Service application in Visual C#

This article describes how to create a setup project for a Windows Service application (formerly named an “NT service”). To do this, you must first create a solution that contains a simple Windows Service project that writes an entry to its application log. You then add a setup project to the solution to install the Window Service. Finally, you start the service. You can start the service by using the Services item in the Administrative Tools folder in the Start menu.

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you must have:

  • Microsoft Windows 2000, Windows XP, Windows Server 2003, or a later Microsoft operating system with the .NET Framework installed
  • Microsoft Visual Studio .NET Enterprise, Microsoft Visual Studio .NET Enterprise Architect, Microsoft Visual Studio 2005, or Microsoft Visual Studio 2008.

This article assumes that you are familiar with Windows Services. If you are not familiar with Windows Services, see the first reference in the REFERENCES section of this article.

This article also assumes that the user account that you use to install and to run this service has the permissions that you must have to install and to start services, and also has the permissions that you must have to access the event log.

Create a Setup Project for a Windows Service

This section describes how to create a Windows Service project, and how to use a compiled setup project to install the Windows Service.

Create a Windows Service Project

  1. Start Microsoft Visual Studio.
  2. On the File menu, point to New, and then click Project.
  3. Click Visual C# Projects under Project Types, and then click Windows Service under Templates.Note In Visual Studio 2005 or Visual Studio 2008, expand Visual C# under Project Types, clickWindows, and then click Windows Service under Templates.
  4. Type LogWriterService in the Name text box, and then type C:\ in the Location text box. Click OK.
  5. In Solution Explorer, right-click Service1.cs, and then click View Code.
  6. In the OnStart event handler, replace the comments with the following code:
    EventLog.WriteEntry("My simple service started.");
  7. In Solution Explorer, double-click Service1.cs.
  8. In the Code Editor window, right-click Design View, and then click Properties
  9. In the Properties pane, click the Add Installer link.
  10. In the Properties pane for ServiceInstaller1, change the ServiceName property to Service1.
  11. In the Code Editor window in Design view, click ServiceProcessInstaller1.
  12. In the Properties pane, change the Account property to LocalSystem (The LocalService andNetworkService values are available only in Microsoft Windows XP).

Use a Compiled Setup Project to Install the Windows Service

After you complete the steps in the previous section to configure the Windows Service project, follow these steps to add a deployment project that packages the service application so that the service application can be installed:

  1. Add a new project to your LogWriterService project. To do this, follow these steps:
    1. In Solution Explorer, right-click Solution ‘LogWriterService’ (1 project), point to Add, and then click New Project.
    2. Click Setup and Deployment Projects under Project Types, and then click Setup Projectunder Templates.
    3. In the Name text box, type ServiceSetup.
    4. Type C:\ in the Location text box, and then click OK.
  2. Tell the deployment project what to package. To do this, follow these steps:
    1. In Solution Explorer, right-click ServiceSetup, point to Add, and then click Project Output
    2. In the Add Project Output Group dialog box, in the Project box, click LogWriterService
    3. Click Primary Output, and then click OK.
  3. For correct installation, add only primary output. To add the custom actions, follow these steps:
    1. In Solution Explorer, right-click ServiceSetup, point to View, and then click Custom Actions
    2. Right-click Custom Actions, and then click Add Custom Action.
    3. Click Application Folder, and then click OK.
    4. Click Primary output from LogWriterService (Active), and then click OK.Notice that Primary output appears under InstallCommitRollback and Uninstall.
  4. By default, setup projects are not included in the build configuration. To build the solution, use one of the following methods:
    • Method 1
      1. Right-click LogWriterService, and then click Build.
      2. Right-click ServiceSetup, and then click Build.
    • Method 2
      1. On the Build menu, click Configuration Manager to build the whole solution.
      2. Click to select the Build check box for ServiceSetup.
      3. Press F7 to build the whole solution. When the solution is built, you have a complete installation package that is available for the service.
  5. To install the newly built service, right-click ServiceSetup, and then click Install.
  6. In the ServiceSetup dialog box, click Next three times. Notice that a progress bar appears while the service installs.
  7. When the service is installed, click Close.

Complete Code Listing

Service1.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;

namespace LogWriterService
{
	public class Service1 : System.ServiceProcess.ServiceBase
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Service1()
		{
			// The Windows.Forms Component Designer must have this call.
			InitializeComponent();

			// TODO: Add any initialization after the InitComponent call
		}

		// The main entry point for the process
		static void Main()
		{
			System.ServiceProcess.ServiceBase[] ServicesToRun;

			// More than one user service may run in the same process. To add
			// another service to this process, change the following line to
			// create a second service object. For example,
			//
			//   ServicesToRun = New System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
			//
			ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };

			System.ServiceProcess.ServiceBase.Run(ServicesToRun);
		}

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
			this.ServiceName = "Service1";
		}

		/// <summary>
		/// Clean up any resources that are being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		/// <summary>
		/// Set things in motion so your service can do its work.
		/// </summary>
		protected override void OnStart(string[] args)
		{
			EventLog.WriteEntry("My simple service started.");
		}

		/// <summary>
		/// Stop this service.
		/// </summary>
		protected override void OnStop()
		{
			// TODO: Add code here to perform any tear-down necessary to stop your service.
		}
	}
}

Verify That It Works

  1. In Control Panel, double-click Administrative Tools, and then double-click Services
  2. Right-click Service1, and then click Start
  3. Use one of the following methods to verify that an event is logged in the event log:
    • Method 1
      1. In Control Panel, double-click Administrative Tools, and then double-click Event Viewer.
      2. Click Application Log in the left pane, and then locate the event log for your service from the right pane.
    • Method 2
      1. In Server Explorer, expand Servers, expand ComputerName, expand Event Logs, expand Application, and then expand Service1. Recall that Service1 is the name of the class, not the service itself. Therefore, Service1 is used as the application name. (It is beyond the scope of this article to explain how to customize the names.)
      2. Move the cursor over the log entries. The second entry from the top should read “My simple service started”.

Referenced by: http://support.microsoft.com/kb/816169

10 Tips to Improve your LINQ to SQL Application Performance

Hey there, back again. In my first post about LINQ I tried to provide a brief(okay, bit detailed) introduction for those who want to get involved with LINQ to SQL. In that post I promised to write about a basic integration of WCF and LINQ to SQL working together, but this is not that post.

Since LINQ to SQL is a code generator and an ORM and it offers a lot of things, it is normal to be suspicious about performance of it. These are right up to a certain point as LINQ comes with its own penalties. But there are several benchmarks showing that DLINQ brings us up to %93 of the ADO.NET SQL DataReader performance if optimizations are done correctly.

Hence I summed up 10 important points for me that needs to be considered during tuning your LINQ to SQL’s data retrieval and data modifying process:

1 – Turn off ObjectTrackingEnabled Property of Data Context If Not Necessary

If you are trying only to retrieve data as read only, and not modifying anything, you don’t need object tracking. So turn it off using it like in the example below:

using (NorthwindDataContext context = new NorthwindDataContext())
{
  context.ObjectTrackingEnabled = false;
}

This will allow you to turn off the unnecessary identity management of the objects – hence Data Context will not have to store them because it will be sure that there will be no change statements to generate.

2 – Do NOT Dump All Your DB Objects into One Single DataContext

DataContext represents a single unit of work, not all your database. If you have several database objects that are not connected, or they are not used at all (log tables, objects used by batch processes,etc..). These objects just unnecessarily consume space in the memory hence increasing the identity management and object tracking costs in CUD engine of the DataContext.

Instead think of separating your workspace into several DataContexts where each one represents a single unit of work associated with it. You can still configure them to use the same connection via its constructors to not to loose the benefit of connection pooling.

3 – Use CompiledQuery Wherever Needed

When creating and executing your query, there are several steps for generating the appropriate SQL from the expression, just to name some important of them:

  1. Create expression tree

  2. Convert it to SQL

  3. Run the query

  4. Retrieve the data

  5. Convert it to the objects

As you may notice, when you are using the same query over and over, hence first and second steps are just wasting time. This is where this tiny class in System.Data.Linq namespace achieves a lot. With CompiledQuery, you compile your query once and store it somewhere for later usage. This is achieved by static CompiledQuery.Compile method.

Below is a Code Snippet for an example usage:

Func<NorthwindDataContext, IEnumerable<Category>> func =
CompiledQuery.Compile<NorthwindDataContext, IEnumerable<Category>>
   ((NorthwindDataContext context) => context.Categories.
      Where<Category>(cat => cat.Products.Count > 5));

And now, “func” is my compiled query. It will only be compiled once when it is first run. We can now store it in a static utility class as follows :

/// <summary>
/// Utility class to store compiled queries
/// </summary>
public static class QueriesUtility
{
/// <summary>
  /// Gets the query that returns categories with more than five products.
  /// </summary>
  /// <value>The query containing categories with more than five products.</value>
  public static Func<NorthwindDataContext, IEnumerable<Category>>
    GetCategoriesWithMoreThanFiveProducts
    {
      get
      {
        Func<NorthwindDataContext, IEnumerable<Category>> func =
          CompiledQuery.Compile<NorthwindDataContext, IEnumerable<Category>>
          ((NorthwindDataContext context) => context.Categories.
            Where<Category>(cat => cat.Products.Count > 5));
        return func;
      }
    }
}

And we can use this compiled query (since it is now a nothing but a strongly typed function for us) very easily as follows:

using (NorthwindDataContext context = new NorthwindDataContext())
{
QueriesUtility.GetCategoriesWithMoreThanFiveProducts(context);
}

Storing and using it in this way also reduces the cost of doing a virtual call that’s done each time you access the collection – actually it is decreased to 1 call. If you don’t call the query don’t worry about compilation too, since it will be compiled whenever the query is first executed.

4 – Filter Data Down to What You Need Using DataLoadOptions.AssociateWith

When we retrieve data with Load or LoadWith we are assuming that we want to retrieve all the associated data those are bound with the primary key (and object id). But in most cases we likely need additional filtering to this. Here is whereDataLoadOptions.AssociateWith generic method comes very handy. This method takes the criteria to load the data as a parameter and applies it to the query – so you get only the data that you need.

The following code below associates and retrieves the categories only with continuing products:

using (NorthwindDataContext context = new NorthwindDataContext())
{
DataLoadOptions options = new DataLoadOptions();
  options.AssociateWith<Category>(cat=> cat.Products.Where<Product>(prod => !prod.Discontinued));
  context.LoadOptions = options;
}

5 – Turn Optimistic Concurrency Off Unless You Need It

LINQ to SQL comes with out of the box Optimistic Concurrency support with SQL timestamp columns which are mapped to Binarytype. You can turn this feature on and off in both mapping file and attributes for the properties. If your application can afford running on “last update wins” basis, then doing an extra update check is just a waste.

UpdateCheck.Never is used to turn optimistic concurrency off in LINQ to SQL.

Here is an example of turning optimistic concurrency off implemented as attribute level mapping:

[Column(Storage=“_Description”, DbType=“NText”,
            UpdateCheck=UpdateCheck.Never)]
public string Description
{
get
  {
    return this._Description;
  }
  set
  {
    if ((this._Description != value))
    {
      this.OnDescriptionChanging(value);
      this.SendPropertyChanging();
      this._Description = value;
      this.SendPropertyChanged(“Description”);
      this.OnDescriptionChanged();
    }
  }
}

6 – Constantly Monitor Queries Generated by the DataContext and Analyze the Data You Retrieve

As your query is generated on the fly, there is this possibility that you may not be aware of additional columns or extra data that is retrieved behind the scenes. Use Data Context’s Log property to be able to see what SQL are being run by the Data Context. An example is as follows:

using (NorthwindDataContext context = new NorthwindDataContext())
{
  context.Log = Console.Out;
}

Using this snippet while debugging you can see the generated SQL statements in the Output Window in Visual Studio and spot performance leaks by analyzing them. Don’t forget to comment that line out for production systems as it may create a bit of an overhead. (Wouldn’t it be great if this was configurable in the config file?)

To see your DLINQ expressions in a SQL statement manner one can use SQL Query Visualizer which needs to be installed separately from Visual Studio 2008.

7 – Avoid Unnecessary Attaches to Tables in the Context

Since Object Tracking is a great mechanism, nothing comes for free. When you  Attach an object to your context, you mean that this object was disconnected for a while and now you now want to get it back in the game. DataContext then marks it as an object that potentially will change – and this is just fine when you really intent to do that.

But there might be some circumstances that aren’t very obvious, and may lead you to attach objects that arent changed. One of such cases is doing an AttachAll for collections and not checking if the object is changed or not. For a better performance, you should check that if you are attaching ONLY the objects in the collection those are changed.

I will provide a sample code for this soon.

8 – Be Careful of Entity Identity Management Overhead

During working with a non-read only context, the objects are still being tracked – so be aware that non intuitive scenarios this can cause while you proceed. Consider the following DLINQ code:

using (NorthwindDataContext context = new NorthwindDataContext())
{
var a = from c in context.Categories
  select c;
}

Very plain, basic DLINQ isn’t it? That’s true; there doesn’t seem any bad thing in the above code. Now let’s see the code below:

using (NorthwindDataContext context = new NorthwindDataContext())
{
var a = from c in context.Categories
  select new Category
  {
    CategoryID = c.CategoryID,
    CategoryName = c.CategoryName,
    Description = c.Description
  };
}

The intuition is to expect that the second query will work slower than the first one, which is WRONG. It is actually much faster than the first one.

The reason for this is in the first query, for each row the objects need to be stored, since there is a possibility that you still can change them. But in the 2nd one, you are throwing that object away and creating a new one, which is more efficient.

9 – Retrieve Only the Number of Records You Need

When you are binding to a data grid, and doing paging – consider the easy to use methods that LINQ to SQL provides. These are mainly Take and Skip methods. The code snippet involves a method which retrieves enough products for a ListView with paging enabled:

/// <summary>
/// Gets the products page by page.
/// </summary>
/// <param name=”startingPageIndex”>Index of the starting page.</param>
/// <param name=”pageSize”>Size of the page.</param>
/// <returns>The list of products in the specified page</returns>
private IList<Product> GetProducts(int startingPageIndex, int pageSize)
{
using (NorthwindDataContext context = new NorthwindDataContext())
  {
    return context.Products
           .Take<Product>(pageSize)
           .Skip<Product>(startingPageIndex * pageSize)
           .ToList<Product>();
   }
}

10 – Don’t Misuse CompiledQuery

I can hear you saying “What? Are you kiddin’ me? How can such a class like this be misused?”

Well, as it applies to all optimization LINQ to SQL is no exception:

“Premature optimization is root all of evil” – Donald Knuth

If you are using CompiledQuery make sure that you are using it more than once as it is more costly than normal querying for the first time. But why?

That’s because the resulting function coming as a CompiledQuery is an object, having the SQL statement and the delegate to apply it. It is not compiled like the way regular expressions are compiled. And your delegate has the ability to replace the variables (or parameters) in the resulting query.

That’s the end folks, I hope you’ll enjoy these tips while programming with LINQ to SQL. Any comments or questions via sidarok at sidarok dot com or here to this post are welcome.

Referenced by: http://www.sidarok.com/web/blog/content/2008/05/02/10-tips-to-improve-your-linq-to-sql-application-performance.html

Barcode Image Generation Library

Posted by:  Brad Barnhill

screenshot.jpg

Introduction

This article and its code provides a way for developers to put barcodes into their applications. It allows for the generation of barcode images without the use of “barcode fonts”. This need arose out of the necessity for one of my own projects to use barcodes and the lack of free libraries on the web to do the job.

To give an idea of what happens in this library: it first turns the data into a series of 1s and 0s representing equal-width bars and spaces. This string of binary information is then sent to a drawing function that converts it to an image representing the desired barcode. This approach allows for one common drawing method to be used on all symbologies.

Supported Encoding Types

Code 128 Code11 Code 39 (Extended / Full ASCII)
Code 93 EAN-8 EAN-13
UPC-A UPC-E JAN-13
MSI ISBN Standard 2 of 5
Interleaved 2 of 5 PostNet UPC Supplemental 2
UPC Supplemental 5 Codabar ITF-14
Telepen FIM (Facing Identification Mark)

** Keep in mind that some symbologies go by more than one name, so make sure the one you are using isn’t listed above by a different name before contacting me to add it. If it isn’t listed above and you would like me to look at adding it to this library, please post a comment below, and I will take a look at it as soon as possible. (Bugs are always a priority, so please send me bug reports.)

Using the Code

The library contains a class called BarcodeLib. There are three constructors:

 Collapse | Copy Code
Barcode();
Barcode(string);
Barcode (string, BarcodeLib.TYPE);

If you decide to create an instance with parameters, the parameters are as follows: the string is the data to be encoded into the barcode, and BarcodeLib.TYPE is the symbology to encode the data with. If you do not choose to specify the data and type at the time the instance is created, you may specify them through the appropriate property later on (but before you encode).

 Collapse | Copy Code
BarCodeLib.Barcode b = new BarCodeLib.Barcode(BarCodeLib.TYPE.UPCA,
          "038000356216", Color.Black, Color.White, 300, 150);

To get the image representing the data generated, you must then call one of the many Encode functions.

 Collapse | Copy Code
public Image Encode(TYPE iType, string StringToEncode, int Width, int Height)
public Image Encode(TYPE iType, string StringToEncode,
        Color ForeColor, Color BackColor, int Width, int Height)
public Image Encode(TYPE iType, string StringToEncode, Color ForeColor, Color BackColor)
public Image Encode(TYPE iType, string StringToEncode)
Encode(TYPE iType)
Encode()

The resulting Image contains the barcode in image format. More functionality has been added, so you can save theImage once it is encoded.

 Collapse | Copy Code
public void SaveImage(string Filename, SaveTypes FileType)

This function can be used by specifying the full path (filename included) of the location you would like to save the image to as a string. The second parameter is an enumerator (BarcodeLib.SaveTypes) that represents the supported types (JPG, BMP, PNG, GIF, TIFF) of files you can save. Functionality has been added so that you can now set the IncludeLabel parameter to allow it to draw the data that’s encoded in the barcode, below the image, as a label. Keep in mind that this will take up some of the space you specify for the size of the image.

 Collapse | Copy Code
b.IncludeLabel = true;

This is used to put the data encoded at the bottom of the image. If you do not set this parameter, it will just generate the barcode without the data at the bottom.

Points of Interest

Writing this library offered me the chance to become intimately familiar with how barcode symbologies work and how the symbologies differ from one another.

A new property has been added to allow exportation of the image and properties in XML format. Keep in mind that thebarcode must be encoded first before this property is read; otherwise, an error will be thrown to notify you of this mistake.

 Collapse | Copy Code
b.XML

History

    • October 10, 2007
      • Initial release (bugs most certainly exist, and a couple of symbologies need to be modified/implemented).
    • October 16, 2007
      • Updated Encode_Code39() to fix a bug that didn’t include inter-character spaces.
      • Also, updated the function Generate_Image(Color, Color), and replaced the section usingSetPixel with the following:
 Collapse | Copy Code
using (Graphics g = Graphics.FromImage(b))
{
    g.DrawLine(new Pen(c), x, 0, x, b.Height);
    g.DrawLine(new Pen(c), x + 1, 0, x + 1, b.Height);
}//using
    • October 17, 2007
      • Changed the Generate_Image(Color, Color) function again to be a little more efficient. Instead of drawing two lines, it just uses a 2px-wide pen now.
 Collapse | Copy Code
using (Graphics g = Graphics.FromImage(b))
{
    g.DrawLine(new Pen(c, (float)2), new Point(x, 0),
    new Point(x, b.Height));
}//using
      • Added the ability to call BarcodeLib.Generate_Labels(Image), it will add the label showing the data encoded at the bottom of the barcode.
      • Fixed a bug in the Test application where, if you encoded with PostNet as the type, it would automatically try to put the label at the bottom and labels aren’t available on PostNet images. This caused it to throw an error that a try{}catch{} can handle for now. 
      • Took c0ax_lx’s advice and moved…
         Collapse | Copy Code
        using (Graphics g = Graphics.FromImage(b))

        … outside the while loop to improve resource usage.

    • October 26, 2007
      • Article edited and moved to the main CodeProject article base.
    • November 1, 2007
      • Complete restructuring of the library to abstract portions of it. Should be much cleaner to look at.
      • An interface was added to force any updates to adhere to the structure.
      • There were some bugs that were fixed in this release.
      • Some of the encoding types on the menu were encoding with a different type than they said.
      • Changed CheckNumericOnly() to be one line of code instead of a massive O^2 complicated take. (Thanks, Pete!)
    • December 9, 2007
      • Bug fixed in UPC-E encoding that would cause an index-out-of-range exception to be thrown. (Thanks Luca Z.)
 Collapse | Copy Code
int pos = 0;
      • This library is getting better with the help of people like Luca and Pete. Keep up the good work, friends.
    • April 16, 2008
      • Code 128 support (beta) (the FNC* chars are still not encoding right… I have to figure that out), but … it’s at least here for your trial and for your comments.
      • Also, there were a few country codes left out of the EAN-13 assigning country lookup. I added what I could find that I left out.
      • Changed the CheckNumericOnly() back to a more complex task because some data being encoded was longer than what Int64.TryParse(string, out) could handle … so back to a more complex, but still a faster, task than comparing each char. Now, I break the string into pieces and test each piece.
    • May 3, 2008
      • Code 128 had some bug fixes added.
      • One was present in InsertStartandCodeCharacters().
      • Bug fixed when trying to encode an apostrophe, it needed an escape character when selecting the data for it from the dataset.
    • May 27, 2008
      • PostNet now supports 5, 6, 9, 11 digit data.
      • Also, a bug with the check-digit for PostNet is fixed.
      • Code 128 now supports specifying and locking the encoding to a specific type (Code A, B, C).
      • Code 39 Extended (Full ASCII) is now supported.
    • May 29, 2008
      • Bug fixed (thanks Koru.nl) in Bitmap Generate_Image(Color DrawColor, Color BackColor)that caused the drawing to be off by one horizontal pixel. This caused the drawing to cut 1 pixel width off the first bar that was drawn if it was drawn up against the edge of the image.
      • The drawing function also changed a bit to eliminate the variable int x; from the function.
      • All positions are now calculated off the variable int pos;, which cuts out one unnecessary and confusing variable.
    • July 30, 2008
      • Bug fixed (thanks Kazna4ey and WolfgangRoth) in init_Code128() that caused .Select(string filterExpression) to return the wrong rows due to case insensitivity. So, the following was added:
 Collapse | Copy Code
this.C128_Code.CaseSensitive = true;
      • Another function byte[] GetImageData(SaveTypes savetype) was added so that users may request the bytes of the image easily. (Useful if using Crystal Reports, etc.)
    • August 26, 2008
      • Bug fixed (thanks JackyWu2005) in Code128.cs that was preventing the proper start characters from being inserted. This only happened when switching back to A from any other encoding type.
    • October 20, 2008
      • Added ITF-14 and Code93.
      • Fixed a bug in Save As functionality that was not saving files in the selected format.
      • Labels now show checksums except in C128 and C11.
    • December 3, 2008
      • Can now specify image size before encoding.
      • Complete overhaul of the drawing function to allow for dynamic drawing size. Now calculates the bar width based on the specified image size. Removed resize functions due to inaccuracy of the resizing method. The encoding functions have been revamped to reflect these changes (removed some of the overloaded functions referencing the resize functions). Also removed a majority of the

case

         statements from

Generate_Image()

         to simplify it. Updated the article to reflect the changes to the

Encode

      functions and the changes to the drawing functions.
  • February 11, 2009
    • Fixed bug in Code 128C that would not insert a 0 in front of an odd length string of raw data.
    • Fixed a bug (thanks Shaihan Murshed) in Code 39 that let the user encode * in the string of data. This should only be used for starting characters, and is now handled.
    • Fixed a bug in Code 39 that was inserting an extra 0 at the end of the encoded string. This did not affect the validity of the barcodes, it was just not supposed to be there.
    • Added a new property to the library called FormattedData. This value is what is actually encoded. It is formatted for certain types of barcodes, for example, Code 39 requires * in front and behind thebarcode.
  • June 4, 2009 (1.0.0.6)
    • Fixed a bug in Code128-A and Code128-B that would cause it to encode incorrectly due to incorrectly trying to compact the barcode for Code128-C. This functionality is now bypassed if Code128-A or Code128-B is selected.
    • Removed a useless variable bEncoded from BarcodeLib.cs.
    • static methods now support generating the data label (required addition of a parameter to 3 of the 5static methods used to encode).
    • Property now available to retrieve the amount of time (EncodingTime) it took to encode and generate the image. (Might be helpful for diagnostics.)
    • Modified a few error messages to be more descriptive about correcting the problem with data length.
    • The Barcode class now inherits from IDisposable - XML export functionality added to BarcodeLib to allow the data, encoded data, and other properties to be exported in XML along with the image inBase64String format. This includes functionality to GetXML() andGetImageFromXML(BarcodeXML).
    • To go along with the XML functionality, there is now a dataset included that has the basic layout of the XML data to make importing and exporting easy.
    • ImageFormat is now a property to set to select what type of image you want returned (JPEG is default). This can help speed of transferring data if using a Web Service.
    • ITF-14 now draws the label with the proper background color instead of always being white.
  • August 16, 2009 (1.0.0.7)
    • Fixed a bug that allowed non-numeric data to be encoded with Code128-C, a check has been put in place to handle this. It throws an error EC128-6 now, if found to contain something that isn’t in Code128-C.
    • Fixed a bug in GetEncoding() for C128. This would allow Code128-B to switch and dynamically use Code128-A if it couldn’t find a char in its set.
  • November 2, 2009 (1.0.0.8)
    • Changed the use of a Pen object that was not disposed of. This was not causing a problem, just bad technique.
    • Fixed an encoding issue with C128-B that had a wrong character in its encoding set at one point (U instead of Z in codeset B).
  • January 4, 2010 (1.0.0.9)
    • The UPC-A check digit is now calculated every time whether 11 or 12 digits are passed in. If 12 is passed in and it has got an incorrect check digit, then it is replaced with the correct check digit. This prevents an unscannable barcode from being generated.
    • The EAN13 check digit is now calculated every time whether 12 or 13 digits are passed in. If 13 is passed in and it has got an incorrect check digit, then it is replaced with the correct check digit. This prevents an unscannable barcode from being generated.
    • All errors can be accessed via the BarcodeLib.Errors properties which is a list of separate errors encountered.
    • All symbologies were moved to the BarcodeLib.Symbologies namespace for better organization.
    • The FormattedData property was not being used, so it was removed.
    • The Version property was added to BarcodeLib to allow reading the libraries version number.
  • April 28, 2010 (1.0.0.10)
    • Fixed a bug in Code 39 extended that was erasing the start and stop characters if extended was used.
    • Fixed a bug that if barcodes were aligned left or right, they would cut off a part of the starting or ending bar, which was a drawing bug that’s been present since 1.0.0.0.
    • Fixed a bug in Code 128C that checked for numeric data; if it was bigger than Int64 and was numeric, it would throw an exception saying it was non-numeric data.
    • Fixed a bug in UPC-A that encoded with the same sets as EAN-13 and only CodeA and CodeC should have been used.
    • Made the Version property static so it can be read without creating an instance.
    • Added a LabelFont property to allow the labels font to be changed.
    • Restructured the label drawing functions to take font height and use that to determine the height of the label.
    • Created an IsNumeric function in C128-C to better separate that functionality. Replaced Int64 withInt32 to better allow compatibility with x86 processors.
    • EncodingTime now includes the time to draw the image and not just the encoding.
    • Alignment property added to allow aligning the barcode in the image given if the image space is wider than the drawn barcode. (Default is centered.)
    • Postnet drawing is incorporated into the default drawing case now, which shortens the code and gets rid of some redundant code.
    • Telepen symbology added.
  • July 18, 2010 (1.0.0.11)
    • Fixed a bug in Code 93 that caused four characters to be encoded incorrectly.
    • Fixed a bug where the ITF-14 bearer bars were not drawing evenly.
    • Fixed a bug in Codabar that would report an object not set to a reference error if non-numeric is found.
    • Added property LabelPosition to position label above or below the barcode, and align the label left, right, or center.
    • Added property RotateFlipType to allow rotation/flipping the image before it is returned.
    • Added several of the newer properties to the XML output of GetXML().
    • Removed Codabar start / stop characters in the label.
    • IsNumeric function added to BarcodeCommon so that every symbology has access to it.
  • June 16, 2011 (1.0.0.12)
    • Fixed a bug in drawing of barcodes that caused barcodes to be cut off on the left and right when aligned to the sides.
    • Fixed a bug in the project where the BarcodeXML dataset was corrupt.
    • Added the GetSizeOfImage function that returns the real world coordinates of the EncodedImage.
    • Facing Identification Mark(FIM) symbology added.

License

Follow

Get every new post delivered to your Inbox.