Featured Post

SQL Query in SharePoint

The "FullTextSqlQuery" object's constructor requires an object that has context but don't be fooled. This context will no...

Friday, September 9, 2011

Create a custom WCF NET.TCP service

I recently learned about creating a custom net.tcp service. I thought I'd make a nice step by step post on how to do this. Also, I'd just to note that this a standard WCF service example hosted in IIS 7.

Ok, so this is how to create a super simple net.tcp service

1.
Firstly, create a server application. In this example my server is a simple class library project. Now the only thing you'll need in this project are 4 files (see image). You will also need to add a reference to System.ServiceModel.











 2. UploaderService.svc 

This file needs to contain your servicehost tag. Set the "Service" value to that of your service class (including the namespace) and if you're deploying to the gac, set the assembly information otherwise. In this example I'm going to use CodeBehind. Here is an example of what your svc file should look like:


3. IUploaderService.cs

Add the ServiceContract attribute to your interface and make sure that all methods have the OperationContract attribute as well.

 4. UploaderService.svc.cs

This is your service class. Nothing fancy needs to happen here, just make sure your service implements your interface and you add all required methods. I added a Ping method that returns a simple boolean to help during setting up and debugging.



5. Web.Config

You can either apply settings to your service via code or via configuration settings. In this example I will demonstrate via the configuration settings. There are thousands of settings you can use but I am going to show you the most basic example you will ever need just to get your service working.


so you could literally copy this exact xml doc and just change the address for the service to wherever you plan on deploying it.

6. IIS Setup

So that's the server side code. To deploy the code, drop your svc, config and dll (in a bin folder) into a folder and add it as a virtual directory in a website. 


Last step for your service is to add the net.tcp as an enabled protocol and setup your bindings for your virtual directory. See images below for settings:


Now check whether your service is pingable via http.


7. Calling your service from the client application.

You can use one of the service utils to generate some client code to use in your client application but mine isn't working so I just copied the interface from my server to my client (if the interface ever changes you'd have to regenerate a new client file anyways so might as well just copy paste). I then use the interface to create a System.ServiceMode.ChannelFactory instance pointing to my service. Here is a code example:

Your client configuration will look similar to the server except that you won't need the service behaviour settings and instead, add the .net version type in the supportedRuntime setting.

 
Run your application and see if you can ping your service.

8. Debugging

If you receive any errors, you can add diagnostics to your config file that will give you more detailed information about the exception that is occurring between the client and the server. Add the following xml to your client application which will output a file in your bin which you can open using the svc tools.



9. Tips

So I made a very silly mistake this week. My web application was set to .NET 2 and my client was set to .NET 4. This obviously did not work so please make sure that the application pool that you are running your site under has the same .NET version as your client application.

Secondly my service's platform was set to 32 bit and my client's was 64 bit. This was also a problem so make sure that they are both built for the same platform.

10. The End

I hope this post helps you. If there is anything I might have missed please let me know and happy net.tcp.ing :)


SharePoint 2010 COM SaveBinaryDirect not reliable

I've recently found that the SharePoint 2010 client object model is not reliable. Calling the SaveBinaryDirect method was working fine for weeks until it started throwing errors. I looked up these errors and found no help. One of the errors I was receiving was "The remote server returned an error: (409) Conflict." Because I was unable to find any information about this error (that was relevant - there was no conflict), we decided to rather create a custom net.tcp service to handle the bulk document uploading.

Tuesday, August 16, 2011

Refreshing a SP.UI.ModalDialog's parent page

Basic javascript post around refreshing a modal dialog's parent page. For some reason I didn't find much help online even though such a common function. The dialog options have a property called "diaglogReturnValueCallback" where you can create a delegate callback to another function - remember that this function must exist on the same page. Then inside the Callback function I check whether the dialog result is "Ok" and then I call location.reload(true); Here's the code

//set the callback delegate
options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);
                   

// the callback function
function CloseCallback(result, target)
{
  if (result == SP.UI.DialogResult.OK)
  {
    location.reload(true);
  }
}

Monday, May 30, 2011

Why does my image become smaller when inserting into Word?

I recently rewrote a report generation system which used to create word documents in Word (running on the server) to a new system which generates these reports in OpenXML. The report output from the new system had to completely match the output from the old system. One of the discrepencies we found was that some images that were being inserted were larger than those in the old system.

With a little investigation I found out that when inserting images into Word, it scales them down to 96 DPI (If larger). One specific image was 300 DPI so when inserting it using OpenXML is was MUCH larger than in the Word Generator output. I've been working with word for 7 years and I've never noticed or knew that this happened!!! Maybe I'm the only one but I thought this was rather interesting - hence this post.
So if you need your OpenXML code to insert your images the same way Word does here is some code to change the dpi of an image if its greater than 96:

Wednesday, April 13, 2011

using Application.ActiveDocument safely

In Word 2007 I would always check whether there were any document in my current application before I call Application.ActiveDocument. This is because if you call this method and there are no documents it would throw an exception.

Now developing in Word 2010, it only gets more complicated. There is now a ActiveProtectedViewWindow as well and this document cannot be retrieved in the applications document list.

So I created a helper method to get the current active document. Here's the code

Monday, March 7, 2011

Issues with AltChunk

I managed to find the underlying problem to a rather annoying bug using AltChunk. I've generated thousands of reports using OpenXml but this one word document would always break xml markup of the document when inserting it using AltChunk.

After stripping the document to only contain the parts that broke it I managed to find out that the "DocumentSettingsPart" contained some elements called SmartTagType. I've never seen these before and not sure what they are used for but the moment I removed them from the document my AltChunk insertion started to work so I now remove them from all my documents before I insert using AltChunk.

I wonder if this is a known bug - will ask on the forum.

Here's some code:

// Get a list of smart tags in the document settings part and remove these
List<SmartTagType> smartTags = mainDocumentPart.DocumentSettingsPart.Settings.Descendants<SmartTagType>();

// Loop backwards otherwise the elements orders change
for (int i = smartTags.Count - 1; i >= 0; i--)
{
  smartTags[i].Remove();
}

Friday, March 4, 2011

Maintain original image size when moving images in open xml

When inserting images into content control boxes using openxml, the image dimensions will not change to those of the image, you will need to manually do this.

Which objects?

There are two places where the image size needs to be set, inside the DocumentFormat.OpenXml.Drawing.Pictures.Picture object and the DocumentFormat.OpenXml.Drawing.Wordprocessing.Inline object. Both of these objects contain an DocumentFormat.OpenXml.Drawing.Wordprocessing.Extent object which contains the Cx and Cy values for the image.

What size?

Now the next problem is knowing what the Cx and Cy values should be set to. Use the System.Drawing.Image object to get the Width and Height properties from your image. However, word image dimensions are not stored in pixels, they are stored in points.

Converting pixels to points can be very complicated when you're working with text but luckily with images there is a constant value we can use to calculate the points from a pixel value, which is 9525.

Code example please?