Moved from Blogger to WordPress

Because I want to do some more blogging and Blogger kinda bums me out, so I decided to move to WordPress. What a difference and what an easy move, it’s just a matter of exporting from Blogger and importing in WordPress, setup some redirects and do the customizations you want. So the next few days, weeks, I’ll be toying around with the site.


Open XML – Setting multiple Picture Content Controls by Tag name, without going crazy

For a project I was working on I had to generate some documents on the server. Not wanting to install Microsoft Word on the server because, well let’s not go there, I’ll have to use bad words; I decided to use Open XML. I started a little C# project to see how this stuff works. At first you frown a little, some cursing and yelling occur; maybe you shed some tears because some simple things turn out to be not that simple, like setting a Picture Content Control. Normally you just fire up Google and look for examples. I did that just that but sadly all examples did something but not just what I wanted: setting multiple Picture Content Controls by Tag name. I found this blog post of Erik White but that code changed all picture content controls when you changed one. That’s because initially a Picture Content Control has some resource Id that points to the same (‘blank’) image in the resources of your document. In another thread some guy Jinesh replied with some code that almost did what I wanted. I used that and added some of my magic to solve this should-be-simple-it’s-2012 problem.

Ok let’s start; first add some using statements and, to prevent some ambiguous (*sigh*) classes, add some aliases.

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;

In this example I’ll use a Bitmap object, this enables me to resize the placeholder using the image dimensions. First I’ll use the Tag name to select the element containing the Picture Content Control, which is a block element. Then I’ll get the Blip element which has a reference to the picture.

Bitmap image = new Bitmap(@"F:insert_me.jpg");
SdtElement controlBlock = _mainDocumentPart.Document.Body
    .Descendants()
        .Where
        (r => 
            r.SdtProperties.GetFirstChild().Val == tagName
        ).SingleOrDefault();
// Find the Blip element of the content control.
A.Blip blip = controlBlock.Descendants().FirstOrDefault();

The next step is to load the image into the document and assign the resource Id of that image to the Blip.Embed property.

// Add image and change embeded id.
ImagePart imagePart = _mainDocumentPart
    .AddImagePart(ImagePartType.Jpeg);
using (MemoryStream stream = new MemoryStream())
{
    image.Save(stream, ImageFormat.Jpeg);
    stream.Position = 0;
    imagePart.FeedData(stream);
}
blip.Embed = _mainDocumentPart.GetIdOfPart(imagePart);

Yes, it’s that simple. You’ve probably seen a lot of different, not working, solutions on the web which had a lot more code. Now the code for the resizing, I suspect there should be an easier way, but for now this will do.

// set image dimensions in the document
DW.Inline inline = controlBlock
    .Descendants().FirstOrDefault();
// 9525 = pixels to points
inline.Extent.Cy = image.Size.Height * 9525; 
inline.Extent.Cx = image.Size.Width * 9525;
PIC.Picture pic = inline
    .Descendants().FirstOrDefault();
pic.ShapeProperties.Transform2D.Extents.Cy 
    = image.Size.Height * 9525;
pic.ShapeProperties.Transform2D.Extents.Cx 
    = image.Size.Width * 9525;

Using Custom Task Forms with Nintex Workflow – Example Solution

This is the follow-up post for the Using Custom Task Forms with Nintex Workflow and is an example implementation of the custom task form using dynamic loaded user controls. The way this works is that the CustomForm.aspx is called by the Nintex workflow task along with some parameters. With this a context is created containing some variables associated with the workflow. The content type name is parsed so that the correct user control is loaded. To get start with the solution, please follow these steps:

  1. Deploy the solution from visual studio to your SharePoint site.
  2. Add the workflow to a list (DemoWorkflow.nwf). Create a custom one, doesn’t matter, just so you can start the workflow on a list item.
  3. Edit the script (nintex.contenttype.bat) to set the correct SharePoint URL, and run it.
  4. Start the workflow on a list item, and check the Workflow Tasks list. If everything went right you should have a task here, and when you click it you will see the custom form show a dynamic loaded user control with a link to my wonderful blog.

You can download the solution here.


Using Custom Task Forms with Nintex Workflow

In this blog I want to show you how to create powerful task forms for Nintex using application pages. Later on I will add an example solution with some help functions and a mechanism to use user controls as the forms. (Update: You can find the example solution here.)

Why?

Well, because you want more. Nintex workflow already supports InfoPath or Nintex Forms, but in my opinion tools like this will always have limits the moment you want something more than just editing and validating user input. Sometimes you just want the flexibility of ASP.Net. There is an example of a custom task from in the Nintex SDK. I stripped that example, so that I can use my own forms and handling of tasks. The way this works is that if you want to use a custom application page to handle a Nintex task, you create a content type based on the Nintex Content Types, associate this content type with an custom application page, and to use this in the workflow set the content type of one of the Request actions in the Nintex Workflow.

Step 1 – Create the custom content type

Go to site settings and add the content type. See image for the correct settings.

Figure 1 – Create the Nintex content type

Step 2 – Create the application page

An example solution will be added to the blog later on. Add an application page to a SharePoint solution, reference the Nintex assemblies and inherit the page from ‘Nintex.Workflow.ServerControls.NintexLayoutsBase’. Runtime two parameters will be interesting to use, these are task list id and task list item id. In my example I have a helper to use these parameters to create a context object containing objects relevant to the workflow, task, list, list item etc.

Figure 2 – Code to create the context object

Step 3 – Register application page and content type

This can now be deployed. You now know where you deployed, what the url to the application page is and what the content type’s name is. We want to let Nintex know this too, for this nwadmin.exe is used. This application can be found in the Nintex installation directory. The command is used like this:
nwadmin.exe -o SetTaskForm -siteUrl “http://yoursite/” -contentType “YourContentTypeName” -taskformUrl “_layouts/YourApplicationPage” -formType All -updateChildren Yes

Step 4 – Set the Nintex action to custom content type

Finally, we must tell the workflow action to use the custom content type so that when the user opens the task, our page is shown. Select the correct action you want to use, and set the Task content type. Publish the workflow and you’re done.

Figure 3 – Set the custom content type


Posting data to a WCF Service from a SSIS Data Flow Destination (and debug it)

Currently I’m working on a system that needs to convert different bulk files into single messages. We want to use SSIS to import the files, transform the records into xml messages and send those messages to BizTalk. I’m new to SSIS so I decided to do some little ‘Proof of Concepts’. This post is about calling a (WCF) Service from the Data Flow.

I created a new solution, added an Integration Services project and a Class Library to hold the code. Using a library to hold the code has several advantages, like maintainability and of course write code in C#. The Script Components use Visual Basic for Applications, that’s bad enough. Anyhow, I now add a Data Source and a Script Component, type Destination, to the Data Flow.

Because we need to reference the Class Library in the Scrip Component, I added two commands to the Post-build Events of the Class Library project, one is to register the dll in the GAC (Sign it!), the other so that the SSIS Script Designer can find it:

“C:Program filesMicrosoft Visual Studio 8SDKv2.0BinGacUtil.exe” -i “$(TargetPath)”
Copy “$(TargetDir)$(TargetName).dll” “C:Program FilesMicrosoft SQL Server90SDKAssemblies”

I also added a Data Viewer between de Data Source and the Script Component, this gives you time to Attach the debugger to the SSIS process (DtsDebugHost.exe). I’ll now edit the code of the Script Component so it calls my own class:

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports Omvormer.Components

Public Class ScriptMain
    Inherits UserComponent

    Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
        Dim wcf As WCFDestination = New WCFDestination()
        wcf.ProcessInputRow(Row.Data)
    End Sub

End Class

The Class Library project I make a reference to my WCF Service. Visual Studio automatically adds a proxy class I can use in my code. Now I implement the code to call the Service in my class, not too exciting:

namespace Omvormer.Components
{
    public class WCFDestination
    {
        public WCFDestination() { }

        public void ProcessInputRow(string messageText)
        {
            Omvormer.Components.TGSBToegang.RouteerBerichtClient rbc = new Omvormer.Components.TGSBToegang.RouteerBerichtClient();
            rbc.Open();
            rbc.Routeer(messageText);
            rbc.Close();
        }
    }
}

Ready? No not really, if you start the package now you’ll get an error like this:

‘Could not find default endpoint element that references contract ’XXXXX’ in
the ServiceModel client configuration section. This might be because no
configuration file was found for your application, or because no endpoint
element matching this contract could be found in the client element.’

When you referenced the Service it also created an app.config file containing some configuration for this Service. You’ll have to add this to dtexec.exe.config and/or dtsdebughost.config (Located in your application directory, e.g. C:Program FilesMicrosoft SQL Server90DTSBinn), so the config will look like this:

<configuration>
    <startup>
        <requiredRuntime version="v2.0.50727"/>
    </startup>
    <system.serviceModel>
        <bindings>
            <!-- Yadda Yadda -->
    </bindings>
    <client>
        <!-- Yadda Yadda -->
    </client>
</system.serviceModel>
</configuration>

(Thanks to this post on SSIS Junkie)
Ok that’s it! Feel free to comment, correct me or whatever you can’t resist to post.


Copyright © 2023. All Rights Reserved. [<Developer>] by Flytonic.