Welcome to MSDN Blogs Sign in | Join | Help

Share sourcecode between Silverlight and WPF Applications

Sharing code between Silverlight and WPF Applications has been a returning wish from several of the customers in our Microsoft Innovation Center in Denmark. The base class libraries are very similar, but obviously something is missing in the 3-4 MB Silverlight download you just installed on that iMac in your girlfriends officespace... therefore if you use features in .NET that is not supported by the SL BCL sharing is not possible. As you are compiling your projects to a given runtime the binary sharing is not really an option either. That leaves us with source code sharing - which is close to 100% better than no sharing at all.

Code to share typically include Presentation Models, Controllers, Domain Objects, Data Transfer Objects etc.

It is a good idea to start with the lowest denominator (Silverlight) if you have the choice from the beginning of your project. Some limitations may require you to think completely differently than you would normally if you were starting out with the full featureset of WPF (ex. ICommand) - you will eventually run into grayzones and I will leave it up to your judgement to decide when and how much you can/should share.

One way to achieve code file sharing is to use the "Add As Link" in the "Add Existing Item" dialog in Visual Studio (push the little arrow to get to it)

image

An example is shown below:

image

Notice the "link" icon on the "MyClass.cs" file in the Silverlight project.

If you have code that is not really shared but nice to keep in the shared file you can make use of the C# preprocessor directives. That sounds like a bad thing to do, but you may have to use different namespaces etc. Silverlight projects actually has a SILVERLIGHT "define" allowing you to include specific code simply by writing:

#if SILVERLIGHT
using System.Windows.Media.Animation;
#endif

You will notice that this is grayed out in the FullCLR project (and obviously the directive #if !SILVERLIGHT may be used in the opposite case)

I have just learned about another way of sharing source files that is less visible in the UI (no "linked icon") but seem to solve the exact same problem.

Any comments and other ideas are welcome - i acknowledge that it is kind of simple but it solves most cases where source code sharing is possible.

Posted by jimmytr | 1 Comments
Filed under: ,

Searching...

Unfortunately on g**g** technologies but the idea of a search shell is quite fun - look here

A modern alternative is the Silverlight based search front-end tafiti (not new, but to some people i may be)

Posted by jimmytr | 1 Comments

Distributed Cache

Just stumbled over a "new" distributed cache CTP from Microsoft - codename Velocity

Having played a bit with NCache in the past i welcome this initiative very much - go have a look

Posted by jimmytr | 0 Comments

Simple "Sponsors" WebPart (AdRotator)

Here's a very simple webpart that randomly shows pictures from a picturelibrary. The part is configured with the name of a picturelibrary. Pictures should have the Title property set to the URL of the sponsor web site ... very few lines of code solves the problem:

  1. namespace MyWSSParts
  2. {
  3.     [Guid("815fbeb7-c1d2-46bb-b5cb-ef3db15c474f")]
  4.     public class AdRotatorPart : WebPart
  5.     {
  6.         public AdRotatorPart()
  7.         {
  8.             this.ExportMode = WebPartExportMode.All;
  9.         }
  10.         private string adsLibraryName = string.Empty;
  11.         [Personalizable(true), WebPartStorage(Storage.Shared),
  12.          WebBrowsable(true), WebDisplayName("Picture Library"),
  13.          WebDescription("Library to use")]
  14.         public string AdsLibraryName
  15.         {
  16.             get { return adsLibraryName; }
  17.             set { adsLibraryName = value; }
  18.         }
  19.         protected override void CreateChildControls()
  20.         {
  21.             base.CreateChildControls();
  22.             try
  23.             {
  24.                 if (string.IsNullOrEmpty(adsLibraryName))
  25.                     return;
  26.                 SPWeb web = SPContext.Current.Web;
  27.                 SPList list = web.Lists[adsLibraryName];
  28.                 if (list == null)
  29.                     throw new Exception("The Picture Library [" + adsLibraryName + "] could not be found.");
  30.                 Random rnd = new Random();
  31.                 int resourceIndex = rnd.Next(list.ItemCount);
  32.                 SPListItem li = list.Items[resourceIndex];
  33.                 string webUrl = web.ServerRelativeUrl;
  34.                 if (webUrl != "/")
  35.                 {
  36.                     webUrl = webUrl + "/";
  37.                 }
  38.                 Image imgControl = new Image();
  39.                 imgControl.ImageUrl = webUrl + li.Url;
  40.                 imgControl.ToolTip = li.Title;
  41.                 HyperLink hl = new HyperLink();
  42.                 hl.NavigateUrl = li.Title;
  43.                 hl.Target = "_blank";
  44.                 hl.Controls.Add(imgControl);
  45.                 this.Controls.Add(hl);
  46.             }
  47.             catch (Exception ex)
  48.             {
  49.                 Label label = new Label();
  50.                 label.Text = ex.Message;
  51.                 this.Controls.Add(label);
  52.             }
  53.         }
  54.     }
  55. }

Remember to add it to safecontrols in web.config

<SafeControl Assembly="AdRotatorPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" Namespace="MyWSSParts" TypeName="*" Safe="True" AllowRemoteDesigner="True" />

 

 

 

Posted by jimmytr | 1 Comments

Security tips and code clips [german]

ThinkTecture's Dominick Baier has helped MSDN in Germany to create a number of clips and How-To's covering several aspects of security on the .NET platform.

If you remember any german from school I would recommend you point your browser this way

Posted by jimmytr | 0 Comments
Filed under: ,

Smart Clients from Greece?

Microsoft Code Name "Acropolis" has finally been released to the public as a technology preview.  

Having played with some internal releases it has become clear to me what a huge amount of work the team has put into this technology. I would like to congratulate with this important milestone and will obviously help getting customer feedback.

Features included in Acropolis CTP1 includes:

- Declarative Composition - allows you to declarative program the structure of application components

- Navigation support - manages activation and deactivation of components

- Document Life Time support - manages the life time of a document bject

- Layout Pane  - Split style and tab style UI layout that leverages WPF

- Transition Animation - Prepackage transitions built on WPF

... and all these comes with Application Design Time Support!

Go get your copy here and please provide feedback to our hard-working team in Redmond.

Note: The CTP1 requires the Visual Studio Codename "Orcas" to run - get it here

Posted by jimmytr | 0 Comments
Filed under: ,

SaaS - SDP

A couple of my colleagues from across the pond have recently blogged about SaaS and the so-called Service Delivery Platform. Check it out here

Posted by jimmytr | 0 Comments
Filed under: ,

ISB - Biztalk Services in the sky

If you haven't done so already I recommend you take a look at our latest Biztalk Services CTP from the Connected Systems Division (http://connectedsystems.spaces.live.com/).

Quite a few people has already commented on this and I will just forward you to some of the links I have found interesting:

http://labs.biztalk.net/

http://blogs.msdn.com/stevemar/

http://blogs.msdn.com/clemensv/archive/2007/04/25/internet-service-bus.aspx

 

http://www.dennispi.com/

 Have Fun!

Posted by jimmytr | 0 Comments
Filed under: ,

Writing Test Code with Impersonation

Some of your (unit) tests may be required to run with predefined credentials, and if all your tests should run as one single identity your might as well use the command line runas.exe tool to start your testrunner (or whatever your favorite naming for this is). In some (rare?) occasions you may need to do tests with a large number of different credentials. There is a number of ways to do this and here I will show you two methods: P/Invoke and Windows Communication Foundation (WCF). I don’t feel like explaining a lot today so I’ll just drop you some sample code you can play with.

P/Invoke

using System;

using System.Security.Principal;

using System.Runtime.InteropServices;

using System.Threading;

 

namespace Test

{

    class Program

    {

        static void Main(string[] args)

        {

            User u = new User("joe",string.Empty,"P\"ssw0rd");

            Thread t = new Thread(DoWorkAs);

            t.Start(u);

            Console.ReadLine();

        }

        private static void DoWorkAs(object o)

        {

            User u = o as User;

            //Print user of application

            Console.WriteLine(WindowsIdentity.GetCurrent().Name);

 

            IntPtr hToken = IntPtr.Zero;

            IntPtr hTokenDuplicate = IntPtr.Zero;

 

            if (Win32.LogonUser(u.UserName, u.Domain, u.Password, 2 /*LOGON32_LOGON_INTERACTIVE*/, 0 /*LOGON32_PROVIDER_DEFAULT*/, out hToken))

            {

                if (Win32.DuplicateToken(hToken, 2, out hTokenDuplicate))

                {

                    WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate);

                    WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();

 

                    // domain\username

                    Console.WriteLine(WindowsIdentity.GetCurrent().Name);

 

                    //INVOKE UNIT TEST HERE - or call test controller or whatever you prefer to call it today...

 

                    //revert

                    impersonationContext.Undo();

                    Console.WriteLine(WindowsIdentity.GetCurrent().Name);

                }

            }

            if (hToken != IntPtr.Zero) Win32.CloseHandle(hToken);

            if (hTokenDuplicate != IntPtr.Zero) Win32.CloseHandle(hTokenDuplicate);

        }

 

    }

    public class User

    {

        public User(string u, string d, string p)

        {

            Domain = d;

            UserName = u;

            Password = p;

        }

        public string UserName;

        public string Domain;

        public string Password;

    }

    public class Win32

    {

        // P/Invoke snask

        [DllImport("advapi32.dll", SetLastError = true)]

        public static extern bool LogonUser(

            string lpszUsername,

            string lpszDomain,

            string lpszPassword,

            int dwLogonType,

            int dwLogonProvider,

            out IntPtr phToken);

 

        [DllImport("advapi32.dll", SetLastError = true)]

        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int

           SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);

 

        [DllImport("kernel32.dll", SetLastError = true)]

        public static extern bool CloseHandle(IntPtr hHandle);

    }

}

(Note: In this example I could have used the System.Net.NetworkCredential class instead of the homemade User class)

WCF

using System;

using System.ServiceModel;

using System.Security.Principal;

using System.Threading;

using System.Net;

 

namespace TestWCF

{

    [ServiceContract(Namespace = "NotDefault")]

    public interface IImpersonateTest

    {

        [OperationContract]

        void RunAsTest();

    }

    public class ImpersonateTest : IImpersonateTest

    {

        [OperationBehavior(Impersonation = ImpersonationOption.Allowed)]

        public void RunAsTest()

        {

            Console.WriteLine(

                string.Format("Inside a WCF Service - caller: {0}",

                WindowsIdentity.GetCurrent().Name));

 

            //INVOKE UNIT TEST HERE - or call test controller or whatever you prefer to call it today...

        }

    }

    class Program

    {

        static string _address = "net.pipe://localhost/ImpersonateTest";

        static NetNamedPipeBinding _binding = new NetNamedPipeBinding();

 

        static void Main(string[] args)

        {

            Thread t = new Thread(Server);

            ManualResetEvent mre = new ManualResetEvent(false);

            t.Start(mre);

            mre.WaitOne();

            EndpointAddress epa = new EndpointAddress(_address);

            ChannelFactory<IImpersonateTest> factory = new ChannelFactory<IImpersonateTest>(_binding,_address);

            factory.Credentials.Windows.ClientCredential = new NetworkCredential("joe", "P\"ssw0rd", String.Empty);

            IImpersonateTest proxy = factory.CreateChannel();

            proxy.RunAsTest();

            ((ICommunicationObject)proxy).Close();

            Console.WriteLine("Press <ENTER> to exit.");

            Console.ReadLine();

            t.Abort();

            t.Join();

            Console.WriteLine("Done...");

        }

        static void Server(object o)

        {

            ManualResetEvent mre = o as ManualResetEvent;

            ServiceHost sh = new ServiceHost(typeof(ImpersonateTest));

            try

            {

                sh.AddServiceEndpoint(typeof(IImpersonateTest), _binding, _address);

                sh.Authorization.ImpersonateCallerForAllOperations = true;

                sh.Open();

                mre.Set(); //Ready - client can continue

                Console.WriteLine("Service host opened");

                Thread.Sleep(System.Threading.Timeout.Infinite);

            }

            catch (ThreadAbortException)

            {

                //Abort is called at some point.

            }

            finally

            {

                sh.Close();

                Console.WriteLine("Service host closed");

            }

        }

    }

}

 

 

Posted by jimmytr | 2 Comments
Filed under: , ,

EntLib 3.0 Released

The P&P team has finished the third major release of the enterprise library. See Tom's post for more information. Try the new WCF integration with logging, exception handling and validation application blocks. Download from MSDN

 

Posted by jimmytr | 1 Comments
Filed under: , ,

Updated VSTS Guidance Available

The P&P team has updated guidance related to Visual Studio Team System on Codeplex
Posted by jimmytr | 0 Comments
Filed under:

SaaS Vocabulary

I have found myself explaining SaaS a few times the past weeks and recently found the WIKI pages: http://en.wikipedia.org/wiki/Software_as_a_Service 

Also Lars Fløe Nielsen from SiteCode has a series of good posts on SaaS from the ISV perspective.

And as a final link on SaaS from me this time: saasblogs.com

Posted by jimmytr | 0 Comments
Filed under:

XmlSerialization snippet

I keep writing this code - now I can find it on my blog in the future :-)

public static class StringXmlSerializer

{

   public static string Serialize<T>(T obj)

   {

      XmlSerializer s = new XmlSerializer(typeof(