CSD End-to-End Team Blog

  • Controlling Message Flow to a Service Host

    This post presents a custom service behavior implementation for controlling the message flow to a WCF service host that reads messages from MSMQ.

    Let’s assume that you want to limit the rate at which the service host reads messages from a queue. This requirement usually can be derived from scalability or throttling requirements. And, when the system is “under stress” you want to stop further message consumption.

    The WCF ServiceHostBase class provides a property called “ManualFlowControlLimit” (abbreviated as MFCL throughout the article) to limit the number of messages received by the host. This property behaves as a counter and decremented each time a message is received. The default value of MFCL is Int32.Max which means read with “no limit”. When MFCL’s value is 0, the host does not receive any more messages until it is set to non-zero again.

    Through MFCL, we will limit the rate at which the service host reads messages. We will also monitor system resource usage to stop the message-flow to the host when the system is under stress.

    First, to maintain a max message flow rate to a host, we will set MFCL value to N every t seconds. This way we get approximately max of N/t (messages/sec) flow to the service host. Note that this will be the upper limit as to the throughput of messages to the host. If this value is set higher than what the service can handle, it will only process as many as it can. For example, even if the max flow rate is set to 2000, it is possible that the host will not read 1000 msgs/sec; as it may be limited to only read 150 without being throttled at all.

    In our solution, we will simply use a System.Timers.Timer object that fires every t=2 seconds to set the value of MFCL.  The max flow rate value that is set on the throttling behavior in the configuration file of the service host is used to calculate the value of MFCL.

    Second, to stop message flow when the system is “under stress”, we will set MFCL to 0. In the solution provided in this article, we define system busy state as the case when the current CPU usage exceeds 99%.  We get the current CPU usage using the PerformanceCounter API. Note that in this example we choose a simple diagnostic, CPU usage via performance counter, however you can use a more complex algorithm that could utilize a voting pattern, quota limits, calculations or other performance counters.

    The algorithm is summarized below:

    Every t sec

    Get current CPU usage

    IF current CPU usage is greater than 99

         Set MFCL to 0

    ELSE

         Get Max Flow Rate (MFR)

         Set MFCL to MFR * t

    A sample implementation for the controller is as follows:

    Code Snippet

        internal class ServiceHostFlowController : IDisposable

        {

            const int TimerIntervalSecond = 2;

            Timer updateFlowTimer;

            int maxFlowRate = Int32.MaxValue;

            bool disposed;

           

            PerformanceCounter cpuPerformanceCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");

     

            ServiceHostBase serviceHost;

     

            internal ServiceHostFlowController(ServiceHostBase serviceHostBase, int maxMessageFlowRate)

            {

                serviceHost = serviceHostBase;

                maxFlowRate = maxMessageFlowRate;

                updateFlowTimer = new Timer(ServiceHostFlowController.TimerIntervalSecond * 1000); // msec

     

                // Set initial flow to 0

                MessageFlowLimit = 0;

            

                updateFlowTimer.Elapsed += new ElapsedEventHandler(UpdateFlow);

            }

     

            public void Dispose()

            {

                Dispose(true);

                GC.SuppressFinalize(this);

            }

     

            private void Dispose(bool disposing)

            {

                // Check to see if Dispose has already been called.

                if (!disposed)

                {

                    if (disposing)

                    {

                        // Dispose managed resources.

                        updateFlowTimer.Close();

                        cpuPerformanceCounter.Close();

                    }

     

                    // Note disposing has been done.

                    disposed = true;

                }

            }

     

            private bool IsServerBusy

            {

                get { return cpuPerformanceCounter.NextValue() > 99; }

            }

     

            private int MessageFlowLimit

            {

                set { serviceHost.ManualFlowControlLimit = value; }

            }

     

            internal void UpdateFlow(object source, ElapsedEventArgs e)

            {          

                if (IsServerBusy)

                {

                    MessageFlowLimit = 0;

                    return;

                }          

              

                int flowLimit;

                try

                {

                    flowLimit = checked(maxFlowRate * ServiceHostFlowController.TimerIntervalSecond);

                }

                catch (OverflowException)

                {

                    flowLimit = Int32.MaxValue;

                }

     

                MessageFlowLimit = flowLimit;

            }

     

            internal void Start()

            {

                updateFlowTimer.Start();           

            }

     

            internal void Stop()

            {

                updateFlowTimer.Stop();

            }

        }

     

     

    To add the flow controller to the service host, we define a custom service behavior as follows:

     

    Code Snippet

    public class CustomThrottlingBehaviorExtensionElement : BehaviorExtensionElement

        {

            /// <summary>

            /// If the value is less than or equal to 0

            /// </summary>

            [ConfigurationProperty("maxMessageFlowRate", IsRequired = false, DefaultValue=Int32.MaxValue), IntegerValidator(MinValue=1)]

            public int MaxMessageFlowRate

            {

                get { return (int)base["maxMessageFlowRate"]; }

                set { base["maxMessageFlowRate"] = value; }

            }

     

            protected override object CreateBehavior()

            {

                return new CustomThrottlingBehavior(MaxMessageFlowRate);

            }

     

            public override Type BehaviorType

            {

                get

                {

                    return typeof(CustomThrottlingBehavior);

                }

            }

        }

     

        public class CustomThrottlingBehavior : IServiceBehavior, IDisposable

        {

            ServiceHostFlowController flowController;

            private int maxFlowRate;

     

            public CustomThrottlingBehavior(int maxMessageFlowRate)

            {

                maxFlowRate = maxMessageFlowRate;

            }

     

            public void Dispose()

            {

                Dispose(true);

                GC.SuppressFinalize(this);

            }

     

            protected virtual void Dispose(bool disposing)

            {

                if (disposing)

                {

                    if (flowController != null)

                    {

                        flowController.Dispose();

                    }

                }

            }

     

            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)

            { }

     

            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

            {

                if (maxFlowRate != Int32.MaxValue)

                {

                    // Flow rate throttling is enabled, initilize flow controller

                    flowController = new ServiceHostFlowController(serviceHostBase, maxFlowRate);

                    serviceHostBase.Opened += new EventHandler(serviceHostBase_Opened);

                    serviceHostBase.Closed += new EventHandler(serviceHostBase_Closed);

                }

            }

     

            void serviceHostBase_Closed(object sender, EventArgs e)

            {

                flowController.Stop();

            }

     

            void serviceHostBase_Opened(object sender, EventArgs e)

            {

                flowController.Start();

            }

     

            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

            { }      

        }

     

    Now, the behavior can be added to the service in the web.config file as follows:

    Code Snippet

    <system.serviceModel>

        <bindings>

          <netMsmqBinding>

            <binding name="netMsmqConfig">

              <security mode="None" />

            </binding>

          </netMsmqBinding>

        </bindings>

        <extensions>

          <behaviorExtensions>

            <add name="customThrottlingBehavior" type="ServiceFlowControllerSample.CustomThrottlingBehaviorExtensionElement, ServiceFlowControllerSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ce62a76d7e8bebe"/>

          </behaviorExtensions>

        </extensions>

        <services>

          <service name="ServiceFlowControllerSample.Service1" behaviorConfiguration="ServiceFlowControllerSample.Service1Behavior">

            <!-- Service Endpoints -->       

            <endpoint address="net.msmq://localhost/private/ServiceFlowControllerSample/Service1.svc" binding="netMsmqBinding" bindingConfiguration="netMsmqConfig" contract="ServiceFlowControllerSample.IService1">

              <!--

                  Upon deployment, the following identity element should be removed or replaced to reflect the

                  identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity

                  automatically.

              -->

              <identity>

                <dns value="localhost"/>

              </identity>

            </endpoint>

            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

          </service>

        </services>

        <behaviors>

          <serviceBehaviors>

            <behavior name="ServiceFlowControllerSample.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"/>

              <customThrottlingBehavior maxMessageFlowRate="2"/>

            </behavior>

          </serviceBehaviors>

        </behaviors>

      </system.serviceModel>

     

    Execution and Results

    To verify the implementation, we will use perfmon by adding the following counters to its view.

    (Processor, % Processor Time, _Total)

    (MSMQ Queue, [machineName]\private$\serviceflowcontrollersample\service1.svc)

     

    We start our test by sending 100 messages to the queue. The host starts reading messages at a max flow rate of 2 msgs/sec as set in the configuration. After about half the messages are consumed, we start another app that performs a spin-wait that will allow us simulate busy system by increasing the CPU usage above 99%, which is the stop threshold in our case. As seen in the following picture, no further messages are read from the queue at this time. Next, we stop the spin-wait app to release CPU resources. Observe that the message flow is resumed and number of messages in the queue continues to decline.

    ManualFlowControlLimit_Results

     

     

    by Hülya Pamukçu, May 09

  • Quick Follow-On

    I got a few comments from people inside the team here about my last post – thanks to Colin and Omar, I now have to answer these questions:

    It will be great if you can elaborate “but try to move it strategically where necessary and possible”.  This will be very helpful and critical for those who want to adopt scenario-driven development into their development process.

    And

    From a developer perspective this sounds very exciting. Especially the federated part, because I have yet to find an application that does this efficiently across multiple systems. When I read this, the first thing that pops in my mind is how is Microsoft planning to distribute it? Is the ‘big app’ shipped, shared? Can I get my hands on the source code? When can I get a sneak preview? I know that promising deliverables to the community when we are developing on top of shifting sands sounds a little scary, but as soon as we figure it out, a teaser might not be a bad idea to spark some interest. I think this would be would be worth posting on the next blog. 

    Well indeed – how can I refuse to at least attempt to answer these? Taking the first one first, what I mean is that if we can find a customer scenario that we believe is important but is not currently addressed by the Oslo plan of record, or is not addressed satisfactorily, we should advocate a solution for that scenario to the rest of the Oslo team to get adequate support built into the product. It’s hard to be concrete here, but I’ll try, using an analogy.

    Many people of a certain base geekiness or above build their own computer systems by buying motherboards, processors, memory and so forth and assembling them by hand. A subset of these people go a step further, and overclock these systems to get more out of them than mere specification would allow. However, until relatively recently, overclocking was frowned upon by processor and memory, etc. manufacturers as they couldn’t guarantee that things would keep on working – if you’re operating something beyond its specification, all warranty bets are off, basically. People still wanted to do it, though, and there was a fairly substantial demand to be able to access more of the basic properties of each component directly to allow fine-tuned overclocking.  Some component manufacturers saw a chance for some differentiation here, and began to offer fine tuning parameter access and official overclocking support (e.g. the advent of EPP in DRAM specifications). So what do the others do? Do they cede the overclocking market to those players, or do they also jump in?

    You only need to look at the PC components market now to know the answer – it’s almost impossible to buy a motherboard whose BIOS doesn’t allow for some flavor of overclocking settings, it’s easy (and cheap!) to buy memory designed to be run above specification (or did they just lower the specification? Hmmm) and even the processor manufacturers sell varieties specifically targeted at the overclocking/enthusiast market.

    OK, I suspect this sucks as an analogy (nice story, though, eh?), but if you put us in the shoes of the overclocking community and the Oslo product teams in the place of the component manufacturers, then it sort of hangs together. Just.

    Question 2 is easier to explain but again hard to be absolutely 100% definitive. We intend to ship the app as binaries, as source code, on MSDN, on any distribution DVDs Oslo technologies might find themselves on, with guidance, as samples, as reference material, etc. In short, we have the desire to make the thing broadly available in as large a number of forms as makes sense, as soon as we can.

    It’s the weekend now, so bye.

    Adam (adamde@microsoft.com)

  • Pretending Not To Be Microsoft

    I’ve mentioned off-hand the ‘big app’ we’re building to exercise Oslo thoroughly, the so-called ‘FTA’, and I’ve promised to talk about it but so far have failed to deliver on that promise. Today that changes.

    First, a word of caution: it’s easy to assume that ‘FTA’ is a real product name, or that it should be and intends to be. It isn’t, it probably shouldn’t and it doesn’t. ‘FTA’ is just a large enough and useful enough application that it will stretch the Oslo platform to its limits in some areas and will actually get used by people, which is key to our ‘stretch and stress the platform’ intent.

    First, what is it? ‘FTA’ stands for Federated Task Assistant, which could just be descriptive enough to tell you what it does, but probably isn’t. So, let’s start from this premise: you have a bunch of tasks you have to perform, from a bunch of sources and as parts of many bigger things. For example, I need to order a new credit card because my current one’s magnetic strip is failing; I need to write people’s reviews because it’s that time of year; I have to write a blog entry on ‘FTA’; I have to ensure my wife’s rather substantial list of tasks for me is at least partially addressed, and so forth. Some of these tasks are personal, some are work-related; some get tracked through other systems (like our internal bug tracking system, our HR systems, TFS, and so forth) and some get forgotten if they don’t get tracked (well, for me, that’s most things).

    I want to be able to see all my tasks across all of these different systems in one place, and I want to be able to interact with them (say they’re done, assign them to someone else, change the priority, create new ones, and so forth) no matter where I am. So we wanted to create a system where this can actually be done, hence the ‘FTA’. It turns out, of course, that the ‘FTA’ (can I drop the quotes now? It’s not a real product name, OK?) is the ideal target application for Oslo, because it makes extensive use of workflows, has numerous client, server and cloud components, and integrates with external systems.

    But we have to build it as if we were not an internal Microsoft team. We have to try to think like an ISV, and make decisions based upon our needs rather than our division’s platform strategy.

    To be frank, it’s extremely hard to stick to this, for a number of reasons. First, we are a part of our division’s platform teams, so it’s kind of hard to ignore what we’re all up to. Secondly, to be really good at pretending not to be Microsoft, we’d need to be suitably externally motivated – that is, we’d have to believe in the FTA as a real, standalone product that stands to make us millions, one that we’d like to float off as a separate company so that we can have that money for ourselves. Let’s be honest, that’s not our intent so we’re faking the faking, somewhat. Still, we are making some reasonably independent decisions, often even thoughtfully  J, so it’s working to a degree.

    We really see three competing tensions for our efforts:

    1.       Be an excellent and independent assessor of Oslo’s capabilities, and use our feedback to make the product great. Not just bug reports and feature requests, but try to move it strategically where necessary and possible

    2.       Create an application that everyone in the division, the company, the world wants to use, and get it dog-fooded – heavy use gives us a much better feel for the resilience of the platform to stress, load and all those famous ‘-abilities’

    3.       Create an excellent canonical reference application/sample for the world to use as best practice examples when building applications with Oslo

    Which of these priorities is on top? What do we do when there’s a conflict? Well, then we have to decide if we’re being Microsoft today or not.

    Next time, I’ll dive into some of the FTA’s capabilities and maybe even some architecture.

    Adam (adamde@microsoft.com)

  • Friends With Benefits

    Last time I talked briefly about what the E2E team in CSD is and vaguely what we do. Now I want to get a bit more specific. In particular, I want to justify our existence by explaining how we benefit the development of Oslo and hence our customers.

    Oslo Milestone Scenarios

    Let’s take the milestone scenarios first. The point here is that we try to define, at a very high level, what we believe is achievable as an integrated product at the end of each milestone. Remember that Oslo is comprised of a reasonably large set of quasi-independent product teams, so it’s our job to come up with that ‘all-up’ scenario that together they agree can be achieved. That’s benefit #1 – we have a holistic view of the product and we apply it to achieve integration.

    We started off with the idea that these scenarios would be a set of so-called ‘hello worlds’ – theoretically tiny applications that test and verify a particular aspect of the platform’s capabilities, which is the approach that products like WCF took during its development. However, as Oslo is aimed at entire applications and their lifecycle, we decided that a full-on, sort-of-believably-close-to-real-life scenario made more sense. It turns out that our first intuition wasn’t wrong, though – we still decompose the entire scenario into little chunks (we we rather cutely call them ‘hello moons’, as the entire scenario was still called a ‘hello world’… at the start) and use these chunks both for measurement against plan and as check-in tests to ensure that no-one breaks the scenario as they develop their code.

    Of course, it’s not done in a vacuum, we do it through collaboration and lots of back and forth. At the end of this definition process, we start delving into it in more detail, actually putting together a story of the whole user experience, end to end. This draws out many architectural and design issues between teams, some of which can be resolved there and then by discussion, others of which, our so-called ‘rocks’, are taken away and broken up into smaller, solvable pieces by the teams concerned. There’s benefit #2 – we help to identify and solve the big rocks facing our teams.

    Having come to a story that all the teams believe in and which we broadly agree is achievable across the length of the milestone, we have a quick round of discussions with each product unit, asking them to sign off on their parts of this scenario as the integration deliverable for the milestone. Although we’d like their responses to be “OK, End-to-End overlords, of course we’ll do everything you ask”, more often than not it’s really rather closer to “You must be joking! We can’t do all that! Cut! Cut! Cut!”. So it’s a negotiation J. Benefit #3, then – we drive the milestone goals to sign off and closure.

    As the milestone progresses, we build the scenario. Sometimes, we’ll build it with what’s out there today (as in, real, released software) and gradually modify it to use newer technologies as they come on stream. As we integrate and use all the disparate parts, we become essentially the first customers – we know what the experience is like, what’s good and what’s bad, and we tell the teams. Sometimes we’re subtle and kind, sometimes we’re, err, not. We have an internal blog where we share our frustrations with the use of the technologies in their early stages, and one of my colleagues is now rather famous for her entries in which she plaintively pleaded for serenity! The blog has caused tension, then, but it has mostly been what I call ‘benign tension’, where the ultimate result has been for the overall benefit of the team. Now I’ve skirted over benefit #4 – we act as the first, and very open and honest, customers for Oslo.

    The final benefit we get to claim is that as we build the scenario, we provide a very visceral (our division’s favorite word) feel for how the product is coming together overall. This is benefit #5, then – you can gauge the overall health of the product at a glance by looking at the status of the scenario.

    I’ve been told that my posts are too long, so I’m stopping here today. Next time, I’ll talk about the FTA and how that benefits us, too.

    This part of my earlier post still applies, by the way:

    SDE Pos# 208695

    http://members.microsoft.com/careers/search/details.aspx?JobID=F4EE8DE8-E5C5-499C-9F7F-43563E00A524

    SDE Pos# 214675

    http://members.microsoft.com/careers/search/details.aspx?JobID=7AFF0BF6-0CC0-40A2-B519-7E123B1989AF

    PM Pos# 176223

    http://members.microsoft.com/careers/search/details.aspx?JobID=C4198008-E83A-411C-BB03-7CDC8AECCA49

     You’ll notice that, contrary to what I write here, those jobs are posted as PM and SDE jobs, but that’s just a reflection of the ‘major’ skills we’re looking for.

  • Making Oslo Great

    Hi – I’m Adam Denning, and I’m the PUM of the CSD End-to-End (E2E) team. I want to use my first blog entry here to explain what all that means and to let everyone know about the work we’re doing.

    First, what is CSD? It stands for Connected Systems Division and is probably best characterized as the division that creates the service-oriented application platform components from Microsoft. This means things like BizTalk Server and all its adapters, WCF and WF, messaging and queuing products, and much of the identity and authorization services, such as Windows CardSpace. Many of us are now working on the next major evolution of all of that, code-named ‘Oslo’. Oslo is a bunch of technologies which together make the platform more declarative (that is, you get to express more of what you want to do and less of how you want it to be done), more process-oriented and more distributed. See official word on this at http://www.microsoft.com/soa/products/oslo.aspx.

    Clearly much to debate there, but that’s for another time. (I did have someone just point out that I should emphasize that CSD doesn’t just do stuff that lives on server-type machines – technologies like WCF and WF are used for a variety of purposes. Fair point).

    Secondly, what is E2E? Ours is a small team whose job it is to ensure that Oslo is right and fit for its intended purposes. We do this in two main ways:

    1.       We define/select  – and build – the scenarios that we use to say that a particular milestone is ‘done’; if we can’t build the designated scenario during the integration phase of the milestone, the milestone is not complete. I call this ‘pulling’ Oslo, as we declare up-front (see – declarative!) what we want Oslo to achieve

    2.       We act like a software company in our own right by defining and building a major distributed application that we believe is canonical for Oslo’s intended purposes and is also something that people want to use. This way, we get to evaluate Oslo’s features as they are developed, give our feedback to the teams building it, and help them understand what it takes to convince independent-minded people to use their software. I call this ‘pushing’ Oslo, as it can be used as a lever to ensure that Oslo provides the right set of features.

    This big app is called the FTA – Federated Task Assistant. I want to talk about that in much greater detail in a subsequent post, too. The important thing is that it is a big app which exercises a lot of Oslo technologies and will end up as a key reference sample.

    Thirdly, what is a PUM? It stands for Product Unit Manager, so it’s my job to ensure that the E2E team does its job and is happy about doing it. Given that we’re a small team with a fairly unusual mission for Microsoft, I’ve organized the team somewhat unusually, too. First, I have two senior people acting as architects for the whole team, one mostly for the scenarios work and the other mostly for the FTA. The rub is that these architects are remote, something that remains out of the ordinary for Microsoft. One lives in Virginia, close enough to DC to have electricity, and the other in France, close enough to Marseilles to have cheese and wine of note. But that’s just France all over.

    I then have a set of people who come from a wide variety of backgrounds who are not definitively cast as one of our traditional developer, tester or program manager roles, but who all perform all three. We have a tacky title for them, and it’s in deep need to improvement: ‘DevPMT’ – meaning ‘developer, PM and tester’. The name sucks, I know. Care to rise to the rename challenge? We typically say that each individual ‘majors’ in either dev or PM and then minors in the other role, and everyone is a tester regardless. We also have a full-time SDET – a tester who also codes – because we have so much work that requires that set of skills.

    So, we have an unusual team, at least for Microsoft.

    We also follow some agile processes, most notably SCRUM. While we’re by no means the only team at Microsoft that practices these development methodologies, we remain in the minority. The good news is that it allows us to release new builds of the FTA every five or six weeks, and we can react pretty quickly to customer demand – remember that we’re building the FTA as if we’re an independent software vendor (ISV), so we do have customers (they’re internal right now, but that could change), and we have to satisfy them in order to get maximum usage.

    We’re hiring, of course, and you can see the jobs here:

    SDE Pos# 208695

    http://members.microsoft.com/careers/search/details.aspx?JobID=F4EE8DE8-E5C5-499C-9F7F-43563E00A524

    SDE Pos# 214675

    http://members.microsoft.com/careers/search/details.aspx?JobID=7AFF0BF6-0CC0-40A2-B519-7E123B1989AF

    PM Pos# 176223

    http://members.microsoft.com/careers/search/details.aspx?JobID=C4198008-E83A-411C-BB03-7CDC8AECCA49

     You’ll notice that, contrary to what I write here, those jobs are posted as PM and SDE jobs, but that’s just a reflection of the ‘major’ skills we’re looking for.

    Next time, more on Oslo and the scenarios, and why building them is so beneficial to the Oslo team and therefore, ultimately, to our customers.

  • Outlook Folder Homepage: Hosting WPF, ActiveX and Windows Forms controls

     

    This post discusses the various ways of hosting nested WPF, ActiveX and Windows Forms controls inside an Outlook add-in application by customizing the view of a MAPI folder in Outlook.

    The well known CRM sample in the msdn article* explains the details of how to enable the WebView in a MAPI folder, register, and host a custom Windows Forms control that also allows the display of an existing view control in a folder in Outlook. Figure 1 clarifies what is meant by “existing View Control” -- an ActiveX control that displays the items in a folder in Outlook. This control can be accessed in managed code through the AxMicrosoft.Office.Interop.OutlookViewCtl.AxViewCtl class.

    *Please make sure you understand the concepts explained in the mentioned article, before continuing to read this article.

    Figure 1 Outlook View Control

    Figure 1 Outlook View Control

    In the CRM sample mentioned above, the control that is registered and displayed in the home page of a folder in Outlook is a Windows Forms control that has the structure shown in Figure 2.

    CRM Sample Control Structure

    Figure 2 CRM Sample Control Structure

    What if you would like to host WPF, ActiveX and Windows Forms controls nested in your customization of a folder’s home page view? In the following section, I will try to address the steps necessary to achieve this goal at a basic level. You can adjust the concepts here to apply to your customization scenario.

    First, we are going to create a task folder and set its properties to enable its Web view. To enable our custom folder view, we set the WebViewOn property to true, then set the WebViewUrl property to the path of the .htm file from which we host the custom control. The content of the .htm file appears as follows. For the details of how to register the control, see the attached projects.

    <html><head><style type="text/css">body{overflow: hidden}</style></head>

    <body rightmargin = '0' leftmargin ='0' topmargin ='0' bottommargin = '0' onload='OnBodyLoad()'>

    <script>

                    function OnBodyLoad()

                    {

                                    var oApp = window.external.OutlookApplication;

                                    FolderHomepageUC.Initialize(oApp, 'FolderHomepageDemo');

                    }

    </script>

    <object classid='clsid:e8d844b9-ea32-4e17-a805-f54f55c9d76e' ID='FolderHomepageUC' VIEWASTEXT width='100%' height='100%'/>

    </body></html>

     Having the registered the Windows Forms Control, we can host the WPF control within the home page through ElementHost (MSDN: Hosting a Windows Presentation Foundation Composite Control in Windows Forms).

    WPF Hosted Control Structure

    Figure 3 WPF Hosted Control Structure

    By doing so, we replace the entire view of the folder with our WPF control. But you may need to display the existing ActiveX Outlook View Control, or another ActiveX control together with the WPF control (MSDN: Hosting ActiveX Control in WPF). In that case, you have the following options:

    1.       Host the ActiveX control inside WPF control by using WindowsFormsHost.

    2.       Wrap the ActiveX control with a Windows Forms control and then host inside a WPF control.

    The following section addresses options 1 and 2.

    Figure 4 shows the structure of the control when the ActiveX control is hosted directly in the WPF control using WindowsFormsHost. See the attached related project: FolderHomepageAx_OutlookAddin.

    The xaml file that defines the WPF control appears as follows:

    <UserControl x:Class="FolderHomepage_OutlookAddin.FolderHomepageWpf"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"

        xmlns:ax="clr-namespace:AxMicrosoft.Office.Interop.OutlookViewCtl;assembly=AxInterop.Microsoft.Office.Interop.OutlookViewCtl"

        >

        <Grid>

          <DockPanel>

            <TextBlock Text="This control is generated by the add-in to demonstrate embedded controls, ActiveX, WPF, Windows Forms" DockPanel.Dock="Top" Foreground="Red" Margin="5,5,5,5"/>

           

            <wfi:WindowsFormsHost DockPanel.Dock="Top">

              <ax:AxViewCtl x:Name="ViewControl"/>

            </wfi:WindowsFormsHost>

          </DockPanel>    

        </Grid>

    </UserControl>

    AciveX, WPF Hosted Control Structure

    Figure 4 AciveX, WPF Hosted Control Structure

    Note that when you try to access the ActiveX control in the Initialize method of the WPF control, you may generate an InvalidActiveXStateException. What you can do instead is to use the Loaded event handler of the WPF control to access the ActiveX control, as illustrated in the attached project FolderHomepageAx_OutlookAddin.

    Figure 5 shows the structure of the control when the ActiveX control is hosted in the WPF control through Windows Forms wrapper control. See the attached related project: FolderHomepage_OutlookAddin.

    The xaml file that defines the WPF control appears as follows:

    <UserControl x:Class="FolderHomepage_OutlookAddin.FolderHomepageWpf"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"

        xmlns:owc="clr-namespace:FolderHomepage_OutlookAddin">

        <Grid>

          <DockPanel>

            <TextBlock Text="This control is generated by the add-in to demonstrate embedded controls, ActiveX, WPF, Windows Forms" DockPanel.Dock="Top" Foreground="Red" Margin="5,5,5,5"/>

           

            <wfi:WindowsFormsHost DockPanel.Dock="Top">

              <owc:OutlookViewControl x:Name="OutlookViewControl"/>

            </wfi:WindowsFormsHost>

          </DockPanel>    

        </Grid>

    </UserControl>

    ActiveX, Windows Forms, WPF Hosted Control Structure

    Figure 5 ActiveX, Windows Forms, WPF Hosted Control Structure

    This structure is recommended because it allows the proper initialization of the ActiveX control before it can be used.

     

    Related Projects (VS 2005) - Click here to download*.

    *Please read "Microsoft Sample Code License Terms" included in the download package before using the projects.

    1.       FolderHomepage_OutlookAddin

    2.       FolderHomepageAx_OutlookAddin

    How to see the add-in in action:

    1.       Close Outlook 2007 if it is running.

    2.       Press F5 in Visual Studio to deploy the add-in, this will start Outlook.

    3.       Go to the Tasks module, through your Navigation pane.

    4.       There should be a task folder named FolderHomepageDemo (Figure 6).

    5.       When you click inside the folder, the page with the hosted controls should be displayed.

    Outlook Folder Home Page with Nested Controls 

    Figure 6 Outlook Folder Home Page with Nested Controls

    Note that the text above in the Outlook view control is a TextBlock in the WPF control, as defined in the above xaml file. The Outlook view control is the same ActiveX control, but this time it is hosted in a WPF control!

    Things to consider:

    1.       Folder home pages are enabled only on the default store. As a security issue, they are disabled by default on non-default stores (for details click here).

    2.       Instant search and hit highlighting does not work in the View control.

    3.       The View control does not provide the ability to preview item content in the reading pane (for details click here).

    References:

    1.       Outlook view control initialization and User Control registration:

    MSDN: Outlook Customization for Integrating with Enterprise Applications

    2.       MSDN: Hosting ActiveX Control in WPF

    3.       MSDN: Hosting a Windows Presentation Foundation Composite Control in Windows Forms

    4.       Outlook 2007 Resource Center

    5.   MSDN: Build Office-Based Solutions Using WPF, WCF, And LINQ

     

    by Hülya Pamukçu, Jan 08

     

  • We're at MIX 07

    Darin Miller and Paul Wheeler (your humble narrator) are at the MIX 07 conference, and we want to hear from you about your experiences with the Microsoft's services platform and what you want/need in a services platform that is built for the web.

    If you're at MIX and you'd like to talk to us in person, drop a comment here and we'll get in touch with you. Also, check out my blog for my thoughts on the sessions I'm attending.

     -Paul

  • Welcome to the End-to-End Team Blog

    Welcome to the Connected Systems Division’s (CSD), End-to-End (E2E) team blog! The E2E team is dedicated to driving requirements across the Microsoft platform, and verifying that CSD’s components of that platform integrate well from the standpoint of external customers. The Connected Systems Division is made up Windows Communication Foundation, Windows Workflow, BizTalk Server, Host Integration Server, Windows CardSpace, Active Directory, Identity Lifecycle Management Server, and more.

    We will be using this blog to quickly release samples, customer guidance, and news about the applications we’re building. We also hope that as we accumulate content here it will become a useful place to find answers, either in the posted articles, or by posting questions in comments.

    One of our teams guiding principles is that we should feel your pain, as developers/testers/customers, and fix problems at the source, before they impact you. So please don’t hesitate to post questions and comments about any of the technologies we’re work with, and we’ll make it our mission to answer your questions, or listen to and incorporate your comments into the work we’re doing.

    -The End-to-End Team


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker