Showing posts with label Code structure. Show all posts
Showing posts with label Code structure. Show all posts

Monday, January 11, 2010

Server-side generation of InfoPath email

In a SharePoint based application, we utilize InfoPath Forms Server to serve InfoPath forms. The reason to apply InfoPath are the well-known: to enable business itself to design and maintain the forms, within a rich designer tool [the InfoPath designer]. To make that viable, a design principle is to keep the forms as slim and simple as possible. Meaning, no (complex) business logic embedded in the forms, no code behind, no web services invocation; just restrict to form input and validation. Another advantage of this restricted InfoPath usage, is that business can itself directly deploy the forms. These type of forms do not require FullTrust, nor is it needed to approve and activate them by IT operations in central admin.
A requirement is to email the forms; to a functional mailbox, and conditionally to the end-user him/herself. The latter is flagged by an option on the form. A management requirement is that the mailbox per form type must be configurable, without need to modify the forms. The only allowed management actions on the form level are for altering data collection and form display/layout.
InfoPath provides standard functionality to automatically email the form upon submit. However, because the destination functional mailbox may not be hardcoded in the form (the management requirement); and because of the conditional email copy to end-user would result in a more complex submit option; I rejected that solution approach. Instead I opt for a setup in which the form email handling is done via server side code. The high level design:
  • associate an SPItemEventReceiver for the ItemAdded event of new instances of the Form ContentType. The SPItemEventReceiver can either be associated at the ContentType definition, or per FormLibrary
  • The SPItemEventReceiver handles the emailing of each new added form. One to the configurable functional mailbox. This setting can thus be server side retrieved and applied, and it can be managed without need to modify the form for this. And if the end-user selected so in the form, then also send a copy to the end-user mailbox. This conditional logic can easily be developed within the SPItemEventReceiver handling
To set up the email-version of a submitted form, it is needed to retrieve the form data, and transform that into an email body-message. Design decision here is to apply the same view translation as embedded within the source form template. Rationale for that decision is that the email layout always will correspond with the displayed form layout. In that context, it is desired to retrieve the view stylesheet directly from the source form template self. Then the email layout will remain to automatically follow the form layout, irrespective of changes made in the form layout by business. With this, the steps to setup the email body are:
  1. read in the xmfile associated with the added form item
  2. retrieve the mso-infoPathSolution processing instruction, and parse the name of the source form template
  3. download the source form template, and extract the view stylesheet from the cabinet container
  4. cache the relation <name source form template, view> for later added forms the view can directly be found without need to get it from the source form template
  5. apply the view stylesheet to transform the data of the xmlfile into html
The result is an email message in the same layout as the form rendering within InfoPath Forms Server. Warning: typically the resulting message is too large to be correctly handled by SPUtily.SendMail, so best to apply SmptClient instead for sending the email.

Monday, September 21, 2009

Tip - HowTo package multiple project-assemblies in a single WPF executable

It's a good practice to structure your Visual Studio solution according to the application layers. You can do that via a folder structure within a single project. But I prefer to structure each application layer within it's own VS project. This approach allows (the build of) each VS project to depend only on the architectural layer direct beneath it.
A consequence of structuring within multiple VS projects, is that each project will build its own assembly file. Often this is also required for deployment and update flexibility. Sometimes however its handier to package it all within a single assembly for deployment. An example is the build of a WPF .exe. Especially for a smaller application, it's a bit overdone to have to deploy one or more .dll assemblies besides the .exe.
Luckily it's easy possible to also package the other project-assemblies within the main .exe executable. The tool to the rescue here is ILMerge. You can modify the project file to automatically merge the dependant .dll assemblies within your main .exe:
<PropertyGroup>
<PostBuildEvent>ILMerge.exe /internalize /ndebug /out:$(TargetFileName) $(TargetFileName) TopForce.Communication.Application.dll TopForce.Communication.Integration.dll</PostBuildEvent>
</PropertyGroup>

Monday, June 29, 2009

Apply partial classes to structure a multi-screen webpart

In a recent project I needed to implement a webpart consisting of multiple subscreens. The case is an employee self service application for the expensehandling business process. Usecases herein are to (re)view the status of your earlier entered expenses, and to enter new or modify existing expenses. In the UI design this resulted in 3 separate screens:


1. Overview of entered expenses



2. Details of one expenses



3. Input and edit form for a new expense



For an optimal user experience it is desired to present these different screens while remaining at the same location (thus webpage) in the enterprise portal. This can easily be achieved by incorporating the different screens within a single webpart, and apply a mode-flag to runtime determine which particular screen to render and respond to. A disadvantage of this approach is however that the webpart source file is considerable larger, and also contains different subfunctionalities with minimal cohesion. The solution for this is to structure and divide the webpart code in multiple partial classes. One partial class is the 'master', which delegates dependent on the mode-flag runtime behaviour to one of the 'child' partial classes. Each 'child' partial class contains and provides all the functionality for a single subscreen. End result is that the code is more understandable, and thus better to maintain.