I have read many blogs on this, they talk about checking things like HtmlPage.IsEnabled.
Personally I use Application.Current this will be NULL if you are in design mode.
public static bool InDesignMode()
{
return App.Current == null;
}
Technical content from the staff at 2e2. We are always busy with; SharePoint / moss, c#, records management (EDRM) and anything .net
I have read many blogs on this, they talk about checking things like HtmlPage.IsEnabled.
Personally I use Application.Current this will be NULL if you are in design mode.
public static bool InDesignMode()
{
return App.Current == null;
}
I’ve been learning f# recently, it is a very powerful and elegant language and hopefully we will be using it for real development in the future. One of the first things I tried was writing a version of the classic Fizz-Buzz interview question (for integers from 1 to 100 print Fizz-Buzz if divisible by 15, Fizz if divisible by 3 and Buzz if divisible by 5).
In an effort to massively overcomplicate a trivial question I ended up defining a set of rules that could be applied to arbitrary inputs. The definition of a rule was:
I then set about implementing the mod 3 and mod 5 rules and hit a problem. Ideally we should be able to apply our rules to any integer type, but because of the well known problem of .Net lacking an INumeric/IIntegral interface or equivalent this wasn’t possible and I ended up with separate rules for each integer type:
Not very satisfactory! I really wanted a generic ModThree function that can be applied to any number that supports the mod operator. In fact we can get this behaviour using some Peano style arithmetic:
(Note we must make the function inline so it is not given a concrete type signature on first use)
The key here is are the generic zero and one functions defined in the first two lines. These give a one and a zero of type of the value they are called with. With these defined we can then increment a variable of type ‘b until it is equal to the value passed in of type ‘a. Then we can mod our value of type ‘b. Of course this is hopelessly inefficient if we are modding by a large number.
After writing this I actually discovered that F# has some built in GenericOne and GenericZero functions so we could rewrite our generic mod function as:
So there we have it, a small part of a hideously overcomplicated and inefficient FizzBuzz solution, interesting though.
Recently I have been doing some coding in idoc script, the default scripting language for Oracle UCM. It’s main use as a scripting language is for generating html server-side. Using it can be frustrating as it does not have procedures and has very limited scoping of variables.
One of the fragments I wrote was a depth first enumeration of the website nodes. A recursive function is the most natural to do this, however because idoc it doesn’t have procedures and a stack this cannot be done in the normal way. The solution was to keep a counter to the current recursion depth in a global variable and store the ‘scoped’ variable at each level in another global variable which was suffixed with the current level:
<@dynamichtml diagonal.page.utility.getallnodes@>
<$c="***********************************"$>
<$c=" Retrieves a complete list of nodes for a website in depth first search order (recursive)"$>
<$c="Input variables:"$>
<$c=" siteId : the site to search"$>
<$c=" currentNode : the node to start from"$>
<$c=" AllNodesRs : a result set with one column (nodeId) to add the nodes to"$>
<$c=" level : current level of the depth first search"$>
<$c="Ouput variables:"$>
<$c=" AllNodesRs"$>
<$c="*************************************"$>
<$rsAppendRowValues("AllNodesRs",currentNode)$>
<$setValue("#local","tmpNode"&level, currentNode)$>
<$currentNode=ssGetRelativeNodeId(siteId,currentNode,"child")$>
<$if not strEquals(currentNode,"")$>
<$level=level+1$>
<$include diagonal.page.utility.getallnodes$>
<$level=level-1$>
<$endif$>
<$currentNode=ssGetRelativeNodeId(siteId,getValue("#local","tmpNode"&level),"next")$>
<$if not strEquals(currentNode,"")$>
<$include diagonal.page.utility.getallnodes$>
<$endif$>
<@end@>
And to use this:
<$currentNode=ssGetFirstNodeId(siteId)$>
<$level=0$>
<$rsCreateResultSet("AllNodesRs","node")$>
<$c="We have to set this to ensure we enumerate sections that are set to 'Contributor Only'"$>
<$SSContributor=1$>
<$include diagonal.page.utility.getallnodes$>
<$SSContributor=0$>
The two key lines which store and retrieve the current node for each level of the recursion are:
<$setValue("#local","tmpNode"&level, currentNode)$>and
<$currentNode=ssGetRelativeNodeId(siteId,getValue("#local","tmpNode"&level),"next")$>
Of course you can write an imperative version of any algorithm but some things are more naturally written as a recursion.
NB: for deep sites you can produce a ‘stack overflow’ due to the large number of nested idoc includes.
mutex.WaitOne();
[TestMethod] public static void SimpleCallAsUser() { string yourUser = @"Someone"; // Change me WindowsIdentity wi = new WindowsIdentity(yourUser); WindowsImpersonationContext imp = wi.Impersonate(); string currentUser = Environment.UserName; Assert.AreEqual(yourUser, currentUser, true, "Could not impersonate"); imp.Undo(); }
Environment.Exit(1);
I have been working with the ESB toolkit and following MSDN Social. If you have worked through some of the Development Activities you may have come across How to: Route a Single Message to Multiple Recipients Using an Itinerary Routing Slip.
You may have thought what I thought.. what if I need to use a different transform for each recipient? I would suggest you read the above development activity and understand it, then come back to the blog.
To summarize :
If you select one of the Resolvers you will see that you can specify a transform type. For a route message extender this has no affect. The message will NOT be transformed.
In order for the message to be transformed you need to create your own Custom Itinerary Messaging Service this new service will need to route and transform. You may think this sounds hard, but really.. it’s easy.
I set about creating this, I had reflector open on one window and Visual Studio open on the other. I wanted to reuse the existing ESB code has much as possible (without copy and pasting code blocks). The ESB Assembly Microsoft.Practices.ESB.Itinerary.Services.dll contains the class for each Service, these classes have public methods for transform and route. So all we need to do is call these.
The is the code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Globalization;
using Microsoft.Practices.ESB.Exception.Management;
using Microsoft.Practices.ESB.Resolver;
using Microsoft.Practices.ESB.Itinerary.Services;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Streaming;
namespace Diagonal.ESB.Services
{
public class TransformAndRouteService : IMessagingService
{
public IBaseMessage Execute(IPipelineContext context, IBaseMessage msg, string resolverString, IItineraryStep step)
{
if (context == null)
throw new ArgumentNullException("context");
if (msg == null)
throw new ArgumentNullException("msg");
if (string.IsNullOrEmpty(resolverString))
throw new ArgumentException("Properties.Resources.ArgumentStringRequired", "resolverString");
try
{
msg = route(context, msg, resolverString);
msg = transform(context, msg, resolverString);
return msg;
}
catch (System.Exception ex)
{
EventLogger.Write(MethodInfo.GetCurrentMethod(), ex);
throw;
}
}
private static IBaseMessage transform(IPipelineContext context, IBaseMessage msg, string resolverString)
{
// Get settings for transform to see if we need to call it
ResolverInfo info = ResolverMgr.GetResolverInfo(ResolutionType.Transform, resolverString);
if (info.Success)
{
// if we dont find transform info, we dont mind
Dictionary<string, string> resolverDictionary = ResolverMgr.Resolve(info, msg, context);
string transformMap;
resolverDictionary.TryGetValue("Resolver.TransformType", out transformMap);
if ((!string.IsNullOrEmpty(transformMap)) && (!transformMap.Equals("(None)")))
{
IBaseMessage transformedmessage;
Stream safeDataStream = new ReadOnlySeekableStream(msg.BodyPart.GetOriginalDataStream());
// move the stream pointer back to the start; could theoretically throw an exception if BizTalk
// Server were to return a non-seekable clone of the original stream within GetSafeDataStream
safeDataStream.Position = 0L;
msg.BodyPart.Data = safeDataStream;
// Backup the stream
MemoryStream ms = new MemoryStream();
byte[] respBuffer = new byte[1024];
int bytesRead = safeDataStream.Read(respBuffer, 0,
respBuffer.Length);
while (bytesRead > 0)
{
ms.Write(respBuffer, 0, bytesRead);
bytesRead = safeDataStream.Read(respBuffer, 0,
respBuffer.Length);
}
msg.BodyPart.Data.Position = 0;
TransformationService transform = new TransformationService();
transformedmessage = transform.ExecuteTransform(context, msg, resolverDictionary["Resolver.TransformType"], false);
// restore the stream
ms.Position = 0L;
msg.BodyPart.Data = ms;
return transformedmessage; // Pass back the transformed message
}
}
// not getting transformed.
return msg; // Pass back non transformed message
}
private static IBaseMessage route(IPipelineContext context, IBaseMessage msg, string resolverString)
{
// Pass to routeservice
RoutingService routeService = new RoutingService();
msg = routeService.ExecuteRoute(context, msg, resolverString);
return msg;
}
public string Name
{
get {
System.Diagnostics.Trace.WriteLine("custom code 2");
return "Diagonal.ESB.Services.TransformAndRoute";
}
}
public bool ShouldAdvanceStep(IItineraryStep step, Microsoft.BizTalk.Message.Interop.IBaseMessage msg)
{
return true;
}
public bool SupportsDisassemble
{
get { return true; }
}
}
}
You will need edit the esb.config to allow you to use your new service, add
<itineraryService
id="A5414011-7D60-4670-8AB5-9B6F14C4F0FF"
name="Diagonal.ESB.Services.TransformAndRoute"
type="Diagonal.ESB.Services.TransformAndRouteService, Diagonal.ESB.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bf0fd96c065177b4"
scope="Messaging"
stage="AllReceive"/>
to itineraryServices node.
Once this is in place you can select TransformAndRoute from the list of ServiceNames. When you use this Service the MAP specified by Transform Type will be used to transform the message. You can set this statically , BRE etc. Note if you don’t select a MAP it won’t crash.
I will put the code on codeplex when time permits.
More ESB blogs to follow ;