Dynamic WCF Services (ASP.NET Virtual Paths)<p style="margin-bottom:0in">I have been experimenting with WCF and the ASP.NET VirtualPathProvider. My goal is to host WCF services dynamically (with reflection) in IIS, with no .svc files and no configuration in web.config. With the following code, I think I have succeeded.</p> <p style="margin-bottom:0in"><br></p> <p style="margin-bottom:0in">I am wondering if there are any better approaches to this. It surprises me a little that, when hosted in IIS, WCF does not seem to have any out-of-the-box capacities for adding services at runtime. In other words, WCF makes use of .svc files instead of just treating the services as virtual paths. If WCF handled them virtually, the services could be configured solely in web.config (with no .svc file), or they could be added entirely at run time like they are with non-IIS hosts. This seems superior than what WCF implements.</p> <p style="margin-bottom:0in"><br></p> <p style="margin-bottom:0in">I think this kind of code can be very useful. Consider a web application that consists of many assemblies implementing WCF services. These assemblies are agnostic as to whether or not they are running in IIS. With the virtual approach, the main web application could host all of these services, without the need for the creating .svc files in the main application, which would involve more coupling than would be ideal for an extensible application design.</p> <p style="margin-bottom:0in"><br></p> <p style="margin-bottom:0in">Note that this is basically my first attempt at this -- there may be some bugs in this code.</p> <p></p> <table> <tbody> <tr> <td> <div style="font-size:10pt;background:white;color:black;font-family:Arial"><pre style="margin:0px"><span style="color:green">// VirtualWcf.cs: Load WCF services dynamically (by reflection) under an ASP.NET VirtualPathProvider.</span></pre><pre style="margin:0px"><span style="color:green">// Jason Kresowaty (jason@binarycoder.net)</span></pre><pre style="margin:0px"><span style="color:green">// Use this code at your own risk.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:green">// Supports access to WCF services by paths such as &quot;~/Virtual/TestService.svc&quot;.</span></pre><pre style="margin:0px"><span style="color:green">// The &quot;Virtual&quot; directory and the &quot;ClassName.svc&quot; file do not really exist on disk but are handled by the VirtualPathProvider.</span></pre><pre style="margin:0px"><span style="color:green">// The service is loaded by reflection per the file name contained in the path. In the above example, reflection</span></pre><pre style="margin:0px"><span style="color:green">// would load the class in this same assembly with the namespace-prefixed name &quot;VirtualWcfApp.TestService&quot;.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:green">// You must set up Global.asax to load the VirtualPathProvider:</span></pre><pre style="margin:0px"><span style="color:green">// public class Global : System.Web.HttpApplication</span></pre><pre style="margin:0px"><span style="color:green">// {</span></pre><pre style="margin:0px"><span style="color:green">//  protected void Application_Start(object sender, EventArgs e)</span></pre><pre style="margin:0px"><span style="color:green">//  {</span></pre><pre style="margin:0px"><span style="color:green">//    VirtualWcfPathProvider provider = new VirtualWcfPathProvider();</span></pre><pre style="margin:0px"><span style="color:green">//    HostingEnvironment.RegisterVirtualPathProvider(provider);</span></pre><pre style="margin:0px"><span style="color:green">//  }</span></pre><pre style="margin:0px"><span style="color:green">// }</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:blue">using</span> System;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Collections;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Collections.Generic;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Collections.ObjectModel;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Data;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Configuration;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Web;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Web.Caching;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Web.Hosting;</pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:blue">using</span> System.Globalization;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.IO;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Reflection;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.ServiceModel;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.ServiceModel.Activation;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.ServiceModel.Description;</pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:blue">namespace</span> VirtualWcfApp</pre><pre style="margin:0px">{</pre><pre style="margin:0px">  <span style="color:green">// Shared constants.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">class</span> <span style="color:#2b91af">Shared</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">readonly</span> <span style="color:blue">string</span> VirtualWcfDirectoryName = <span style="color:#a31515">&quot;~/Virtual&quot;</span>; <span style="color:green">// Must start with &quot;~/&quot;, must not end with &quot;/&quot;.</span></pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">readonly</span> <span style="color:blue">string</span> ThisAssemblyFullName = <span style="color:blue">typeof</span>(<span style="color:#2b91af">Shared</span>).Assembly.FullName;</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">readonly</span> <span style="color:blue">string</span> ThisNamespaceName = <span style="color:blue">typeof</span>(<span style="color:#2b91af">Shared</span>).Namespace;</pre><pre style="margin:0px">  }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:green">// This is the VirtualPathProvider that serves up virtual files. The supported</span></pre><pre style="margin:0px">  <span style="color:green">// requests are of the form &quot;~/Virtual/ClassName.svc&quot;.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">class</span> <span style="color:#2b91af">VirtualWcfPathProvider</span> : <span style="color:#2b91af">VirtualPathProvider</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> <span style="color:blue">bool</span> FileExists(<span style="color:blue">string</span> virtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (IsVirtualFile(appRelativeVirtualPath))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">true</span>;</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">else</span></pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> Previous.FileExists(virtualPath);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> System.Web.Hosting.<span style="color:#2b91af">VirtualFile</span> GetFile(<span style="color:blue">string</span> virtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (IsVirtualFile(appRelativeVirtualPath))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">string</span> srp = <span style="color:#2b91af">VirtualPathUtility</span>.MakeRelative(<span style="color:#2b91af">Shared</span>.VirtualWcfDirectoryName + <span style="color:#a31515">&quot;/&quot;</span>, virtualPath);</pre><pre style="margin:0px">        <span style="color:blue">string</span> serviceClass = <span style="color:#2b91af">Shared</span>.ThisNamespaceName + <span style="color:#a31515">&quot;.&quot;</span> + srp;</pre><pre style="margin:0px">        <span style="color:blue">if</span> (serviceClass.EndsWith(<span style="color:#a31515">&quot;.svc&quot;</span>))</pre><pre style="margin:0px">        {</pre><pre style="margin:0px">          serviceClass = serviceClass.Substring(0, serviceClass.LastIndexOf(<span style="color:#a31515">&quot;.svc&quot;</span>));</pre><pre style="margin:0px">        }</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">new</span> <span style="color:#2b91af">WcfVirtualFile</span>(virtualPath, serviceClass, <span style="color:blue">typeof</span>(<span style="color:#2b91af">VirtualWcfFactory</span>).FullName);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">else</span></pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> Previous.GetFile(virtualPath);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> <span style="color:#2b91af">CacheDependency</span> GetCacheDependency(<span style="color:blue">string</span> virtualPath, <span style="color:#2b91af">IEnumerable</span> virtualPathDependencies, <span style="color:#2b91af">DateTime</span> utcStart)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (IsVirtualFile(appRelativeVirtualPath) || IsVirtualDirectory(appRelativeVirtualPath))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">null</span>;</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">else</span></pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">bool</span> IsVirtualFile(<span style="color:blue">string</span> appRelativeVirtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">if</span> (appRelativeVirtualPath.StartsWith(<span style="color:#2b91af">Shared</span>.VirtualWcfDirectoryName + <span style="color:#a31515">&quot;/&quot;</span>, <span style="color:#2b91af">StringComparison</span>.OrdinalIgnoreCase))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">true</span>;</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">return</span> <span style="color:blue">false</span>;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">bool</span> IsVirtualDirectory(<span style="color:blue">string</span> appRelativeVirtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">return</span> appRelativeVirtualPath.Equals(<span style="color:#2b91af">Shared</span>.VirtualWcfDirectoryName, <span style="color:#2b91af">StringComparison</span>.OrdinalIgnoreCase);</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">string</span> ToAppRelativeVirtualPath(<span style="color:blue">string</span> virtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = <span style="color:#2b91af">VirtualPathUtility</span>.ToAppRelative(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (!appRelativeVirtualPath.StartsWith(<span style="color:#a31515">&quot;~/&quot;</span>))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">throw</span> <span style="color:blue">new</span> <span style="color:#2b91af">HttpException</span>(<span style="color:#a31515">&quot;Unexpectedly does not start with ~.&quot;</span>);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">return</span> appRelativeVirtualPath;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px">  }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:green">// This is the virtual .svc file.</span></pre><pre style="margin:0px">  <span style="color:green">// When this file is accessed, a &lt;%@ServiceHost%&gt; tag is returned that gives</span></pre><pre style="margin:0px">  <span style="color:green">// the service and factory associated with this VirtualFile.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">class</span> <span style="color:#2b91af">WcfVirtualFile</span> : <span style="color:#2b91af">VirtualFile</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">string</span> _Service;</pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">string</span> _Factory;</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> WcfVirtualFile(<span style="color:blue">string</span> vp, <span style="color:blue">string</span> service, <span style="color:blue">string</span> factory)</pre><pre style="margin:0px">      : <span style="color:blue">base</span>(vp)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      _Service = service;</pre><pre style="margin:0px">      _Factory = factory;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> <span style="color:#2b91af">Stream</span> Open()</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:#2b91af">MemoryStream</span> ms = <span style="color:blue">new</span> <span style="color:#2b91af">MemoryStream</span>();</pre><pre style="margin:0px">      <span style="color:#2b91af">StreamWriter</span> tw = <span style="color:blue">new</span> <span style="color:#2b91af">StreamWriter</span>(ms);</pre><pre style="margin:0px">      tw.Write(<span style="color:blue">string</span>.Format(<span style="color:#2b91af">CultureInfo</span>.InvariantCulture, </pre><pre style="margin:0px">        <span style="color:#a31515">&quot;&lt;%@ServiceHost language=c# Debug=\&quot;true\&quot; Service=\&quot;{0}\&quot; Factory=\&quot;{1}\&quot;%&gt;&quot;</span>,</pre><pre style="margin:0px">        <span style="color:#2b91af">HttpUtility</span>.HtmlEncode(_Service), <span style="color:#2b91af">HttpUtility</span>.HtmlEncode(_Factory)));</pre><pre style="margin:0px">      tw.Flush();</pre><pre style="margin:0px">      ms.Position = 0;</pre><pre style="margin:0px">      <span style="color:blue">return</span> ms;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px">  }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:green">// This is the factory loaded when the user tried to use the (virtual) .svc</span></pre><pre style="margin:0px">  <span style="color:green">// file. The constructorString is the &quot;Service=&quot; part of the .svc and for our</span></pre><pre style="margin:0px">  <span style="color:green">// purposes identifies the name of the service class (in this assembly) to be</span></pre><pre style="margin:0px">  <span style="color:green">// loaded by reflection.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">class</span> <span style="color:#2b91af">VirtualWcfFactory</span> : <span style="color:#2b91af">ServiceHostFactory</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> System.ServiceModel.<span style="color:#2b91af">ServiceHostBase</span> CreateServiceHost(<span style="color:blue">string</span> constructorString, System.<span style="color:#2b91af">Uri</span>[] baseAddresses)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:#2b91af">Assembly</span> assem = <span style="color:#2b91af">Assembly</span>.Load(<span style="color:#2b91af">Shared</span>.ThisAssemblyFullName);</pre><pre style="margin:0px">      <span style="color:#2b91af">Type</span> serviceType = assem.GetType(constructorString);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:#2b91af">ServiceHost</span> host = <span style="color:blue">new</span> <span style="color:#2b91af">ServiceHost</span>(serviceType, baseAddresses);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">foreach</span> (<span style="color:#2b91af">Type</span> iface <span style="color:blue">in</span> serviceType.GetInterfaces())</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:#2b91af">ServiceContractAttribute</span> attr = (<span style="color:#2b91af">ServiceContractAttribute</span>)<span style="color:#2b91af">Attribute</span>.GetCustomAttribute(iface, <span style="color:blue">typeof</span>(<span style="color:#2b91af">ServiceContractAttribute</span>));</pre><pre style="margin:0px"> </pre><pre style="margin:0px">        <span style="color:blue">if</span> (attr != <span style="color:blue">null</span>)</pre><pre style="margin:0px">        {</pre><pre style="margin:0px">          host.AddServiceEndpoint(iface, <span style="color:blue">new</span> <span style="color:#2b91af">WSHttpBinding</span>(), <span style="color:#a31515">&quot;&quot;</span>);</pre><pre style="margin:0px">        }</pre><pre style="margin:0px">      }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:#2b91af">ServiceMetadataBehavior</span> metadataBehavior = <span style="color:blue">new</span> <span style="color:#2b91af">ServiceMetadataBehavior</span>();</pre><pre style="margin:0px">      metadataBehavior.HttpGetEnabled = <span style="color:blue">true</span>;</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      host.Description.Behaviors.Add(metadataBehavior);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">return</span> host;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px">  }</pre><pre style="margin:0px">}</pre></div></td></tr></tbody></table>© 2009 Microsoft Corporation. All rights reserved.Tue, 17 Mar 2009 20:34:50 Z350f2cb6-febd-4978-ae65-f79735d412dbhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#350f2cb6-febd-4978-ae65-f79735d412dbhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#350f2cb6-febd-4978-ae65-f79735d412dbBinaryCoderhttp://social.msdn.microsoft.com/Profile/en-US/?user=BinaryCoderDynamic WCF Services (ASP.NET Virtual Paths)<p style="margin-bottom:0in">I have been experimenting with WCF and the ASP.NET VirtualPathProvider. My goal is to host WCF services dynamically (with reflection) in IIS, with no .svc files and no configuration in web.config. With the following code, I think I have succeeded.</p> <p style="margin-bottom:0in"><br></p> <p style="margin-bottom:0in">I am wondering if there are any better approaches to this. It surprises me a little that, when hosted in IIS, WCF does not seem to have any out-of-the-box capacities for adding services at runtime. In other words, WCF makes use of .svc files instead of just treating the services as virtual paths. If WCF handled them virtually, the services could be configured solely in web.config (with no .svc file), or they could be added entirely at run time like they are with non-IIS hosts. This seems superior than what WCF implements.</p> <p style="margin-bottom:0in"><br></p> <p style="margin-bottom:0in">I think this kind of code can be very useful. Consider a web application that consists of many assemblies implementing WCF services. These assemblies are agnostic as to whether or not they are running in IIS. With the virtual approach, the main web application could host all of these services, without the need for the creating .svc files in the main application, which would involve more coupling than would be ideal for an extensible application design.</p> <p style="margin-bottom:0in"><br></p> <p style="margin-bottom:0in">Note that this is basically my first attempt at this -- there may be some bugs in this code.</p> <p></p> <table> <tbody> <tr> <td> <div style="font-size:10pt;background:white;color:black;font-family:Arial"><pre style="margin:0px"><span style="color:green">// VirtualWcf.cs: Load WCF services dynamically (by reflection) under an ASP.NET VirtualPathProvider.</span></pre><pre style="margin:0px"><span style="color:green">// Jason Kresowaty (jason@binarycoder.net)</span></pre><pre style="margin:0px"><span style="color:green">// Use this code at your own risk.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:green">// Supports access to WCF services by paths such as &quot;~/Virtual/TestService.svc&quot;.</span></pre><pre style="margin:0px"><span style="color:green">// The &quot;Virtual&quot; directory and the &quot;ClassName.svc&quot; file do not really exist on disk but are handled by the VirtualPathProvider.</span></pre><pre style="margin:0px"><span style="color:green">// The service is loaded by reflection per the file name contained in the path. In the above example, reflection</span></pre><pre style="margin:0px"><span style="color:green">// would load the class in this same assembly with the namespace-prefixed name &quot;VirtualWcfApp.TestService&quot;.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:green">// You must set up Global.asax to load the VirtualPathProvider:</span></pre><pre style="margin:0px"><span style="color:green">// public class Global : System.Web.HttpApplication</span></pre><pre style="margin:0px"><span style="color:green">// {</span></pre><pre style="margin:0px"><span style="color:green">//  protected void Application_Start(object sender, EventArgs e)</span></pre><pre style="margin:0px"><span style="color:green">//  {</span></pre><pre style="margin:0px"><span style="color:green">//    VirtualWcfPathProvider provider = new VirtualWcfPathProvider();</span></pre><pre style="margin:0px"><span style="color:green">//    HostingEnvironment.RegisterVirtualPathProvider(provider);</span></pre><pre style="margin:0px"><span style="color:green">//  }</span></pre><pre style="margin:0px"><span style="color:green">// }</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:blue">using</span> System;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Collections;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Collections.Generic;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Collections.ObjectModel;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Data;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Configuration;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Web;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Web.Caching;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Web.Hosting;</pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:blue">using</span> System.Globalization;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.IO;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.Reflection;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.ServiceModel;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.ServiceModel.Activation;</pre><pre style="margin:0px"><span style="color:blue">using</span> System.ServiceModel.Description;</pre><pre style="margin:0px"> </pre><pre style="margin:0px"><span style="color:blue">namespace</span> VirtualWcfApp</pre><pre style="margin:0px">{</pre><pre style="margin:0px">  <span style="color:green">// Shared constants.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">class</span> <span style="color:#2b91af">Shared</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">readonly</span> <span style="color:blue">string</span> VirtualWcfDirectoryName = <span style="color:#a31515">&quot;~/Virtual&quot;</span>; <span style="color:green">// Must start with &quot;~/&quot;, must not end with &quot;/&quot;.</span></pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">readonly</span> <span style="color:blue">string</span> ThisAssemblyFullName = <span style="color:blue">typeof</span>(<span style="color:#2b91af">Shared</span>).Assembly.FullName;</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">readonly</span> <span style="color:blue">string</span> ThisNamespaceName = <span style="color:blue">typeof</span>(<span style="color:#2b91af">Shared</span>).Namespace;</pre><pre style="margin:0px">  }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:green">// This is the VirtualPathProvider that serves up virtual files. The supported</span></pre><pre style="margin:0px">  <span style="color:green">// requests are of the form &quot;~/Virtual/ClassName.svc&quot;.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">class</span> <span style="color:#2b91af">VirtualWcfPathProvider</span> : <span style="color:#2b91af">VirtualPathProvider</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> <span style="color:blue">bool</span> FileExists(<span style="color:blue">string</span> virtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (IsVirtualFile(appRelativeVirtualPath))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">true</span>;</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">else</span></pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> Previous.FileExists(virtualPath);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> System.Web.Hosting.<span style="color:#2b91af">VirtualFile</span> GetFile(<span style="color:blue">string</span> virtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (IsVirtualFile(appRelativeVirtualPath))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">string</span> srp = <span style="color:#2b91af">VirtualPathUtility</span>.MakeRelative(<span style="color:#2b91af">Shared</span>.VirtualWcfDirectoryName + <span style="color:#a31515">&quot;/&quot;</span>, virtualPath);</pre><pre style="margin:0px">        <span style="color:blue">string</span> serviceClass = <span style="color:#2b91af">Shared</span>.ThisNamespaceName + <span style="color:#a31515">&quot;.&quot;</span> + srp;</pre><pre style="margin:0px">        <span style="color:blue">if</span> (serviceClass.EndsWith(<span style="color:#a31515">&quot;.svc&quot;</span>))</pre><pre style="margin:0px">        {</pre><pre style="margin:0px">          serviceClass = serviceClass.Substring(0, serviceClass.LastIndexOf(<span style="color:#a31515">&quot;.svc&quot;</span>));</pre><pre style="margin:0px">        }</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">new</span> <span style="color:#2b91af">WcfVirtualFile</span>(virtualPath, serviceClass, <span style="color:blue">typeof</span>(<span style="color:#2b91af">VirtualWcfFactory</span>).FullName);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">else</span></pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> Previous.GetFile(virtualPath);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> <span style="color:#2b91af">CacheDependency</span> GetCacheDependency(<span style="color:blue">string</span> virtualPath, <span style="color:#2b91af">IEnumerable</span> virtualPathDependencies, <span style="color:#2b91af">DateTime</span> utcStart)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (IsVirtualFile(appRelativeVirtualPath) || IsVirtualDirectory(appRelativeVirtualPath))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">null</span>;</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">else</span></pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">bool</span> IsVirtualFile(<span style="color:blue">string</span> appRelativeVirtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">if</span> (appRelativeVirtualPath.StartsWith(<span style="color:#2b91af">Shared</span>.VirtualWcfDirectoryName + <span style="color:#a31515">&quot;/&quot;</span>, <span style="color:#2b91af">StringComparison</span>.OrdinalIgnoreCase))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">return</span> <span style="color:blue">true</span>;</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">return</span> <span style="color:blue">false</span>;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">bool</span> IsVirtualDirectory(<span style="color:blue">string</span> appRelativeVirtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">return</span> appRelativeVirtualPath.Equals(<span style="color:#2b91af">Shared</span>.VirtualWcfDirectoryName, <span style="color:#2b91af">StringComparison</span>.OrdinalIgnoreCase);</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">string</span> ToAppRelativeVirtualPath(<span style="color:blue">string</span> virtualPath)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:blue">string</span> appRelativeVirtualPath = <span style="color:#2b91af">VirtualPathUtility</span>.ToAppRelative(virtualPath);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">if</span> (!appRelativeVirtualPath.StartsWith(<span style="color:#a31515">&quot;~/&quot;</span>))</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:blue">throw</span> <span style="color:blue">new</span> <span style="color:#2b91af">HttpException</span>(<span style="color:#a31515">&quot;Unexpectedly does not start with ~.&quot;</span>);</pre><pre style="margin:0px">      }</pre><pre style="margin:0px">      <span style="color:blue">return</span> appRelativeVirtualPath;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px">  }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:green">// This is the virtual .svc file.</span></pre><pre style="margin:0px">  <span style="color:green">// When this file is accessed, a &lt;%@ServiceHost%&gt; tag is returned that gives</span></pre><pre style="margin:0px">  <span style="color:green">// the service and factory associated with this VirtualFile.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">class</span> <span style="color:#2b91af">WcfVirtualFile</span> : <span style="color:#2b91af">VirtualFile</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">string</span> _Service;</pre><pre style="margin:0px">    <span style="color:blue">private</span> <span style="color:blue">string</span> _Factory;</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> WcfVirtualFile(<span style="color:blue">string</span> vp, <span style="color:blue">string</span> service, <span style="color:blue">string</span> factory)</pre><pre style="margin:0px">      : <span style="color:blue">base</span>(vp)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      _Service = service;</pre><pre style="margin:0px">      _Factory = factory;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> <span style="color:#2b91af">Stream</span> Open()</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:#2b91af">MemoryStream</span> ms = <span style="color:blue">new</span> <span style="color:#2b91af">MemoryStream</span>();</pre><pre style="margin:0px">      <span style="color:#2b91af">StreamWriter</span> tw = <span style="color:blue">new</span> <span style="color:#2b91af">StreamWriter</span>(ms);</pre><pre style="margin:0px">      tw.Write(<span style="color:blue">string</span>.Format(<span style="color:#2b91af">CultureInfo</span>.InvariantCulture, </pre><pre style="margin:0px">        <span style="color:#a31515">&quot;&lt;%@ServiceHost language=c# Debug=\&quot;true\&quot; Service=\&quot;{0}\&quot; Factory=\&quot;{1}\&quot;%&gt;&quot;</span>,</pre><pre style="margin:0px">        <span style="color:#2b91af">HttpUtility</span>.HtmlEncode(_Service), <span style="color:#2b91af">HttpUtility</span>.HtmlEncode(_Factory)));</pre><pre style="margin:0px">      tw.Flush();</pre><pre style="margin:0px">      ms.Position = 0;</pre><pre style="margin:0px">      <span style="color:blue">return</span> ms;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px">  }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:green">// This is the factory loaded when the user tried to use the (virtual) .svc</span></pre><pre style="margin:0px">  <span style="color:green">// file. The constructorString is the &quot;Service=&quot; part of the .svc and for our</span></pre><pre style="margin:0px">  <span style="color:green">// purposes identifies the name of the service class (in this assembly) to be</span></pre><pre style="margin:0px">  <span style="color:green">// loaded by reflection.</span></pre><pre style="margin:0px"> </pre><pre style="margin:0px">  <span style="color:blue">public</span> <span style="color:blue">class</span> <span style="color:#2b91af">VirtualWcfFactory</span> : <span style="color:#2b91af">ServiceHostFactory</span></pre><pre style="margin:0px">  {</pre><pre style="margin:0px">    <span style="color:blue">public</span> <span style="color:blue">override</span> System.ServiceModel.<span style="color:#2b91af">ServiceHostBase</span> CreateServiceHost(<span style="color:blue">string</span> constructorString, System.<span style="color:#2b91af">Uri</span>[] baseAddresses)</pre><pre style="margin:0px">    {</pre><pre style="margin:0px">      <span style="color:#2b91af">Assembly</span> assem = <span style="color:#2b91af">Assembly</span>.Load(<span style="color:#2b91af">Shared</span>.ThisAssemblyFullName);</pre><pre style="margin:0px">      <span style="color:#2b91af">Type</span> serviceType = assem.GetType(constructorString);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:#2b91af">ServiceHost</span> host = <span style="color:blue">new</span> <span style="color:#2b91af">ServiceHost</span>(serviceType, baseAddresses);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">foreach</span> (<span style="color:#2b91af">Type</span> iface <span style="color:blue">in</span> serviceType.GetInterfaces())</pre><pre style="margin:0px">      {</pre><pre style="margin:0px">        <span style="color:#2b91af">ServiceContractAttribute</span> attr = (<span style="color:#2b91af">ServiceContractAttribute</span>)<span style="color:#2b91af">Attribute</span>.GetCustomAttribute(iface, <span style="color:blue">typeof</span>(<span style="color:#2b91af">ServiceContractAttribute</span>));</pre><pre style="margin:0px"> </pre><pre style="margin:0px">        <span style="color:blue">if</span> (attr != <span style="color:blue">null</span>)</pre><pre style="margin:0px">        {</pre><pre style="margin:0px">          host.AddServiceEndpoint(iface, <span style="color:blue">new</span> <span style="color:#2b91af">WSHttpBinding</span>(), <span style="color:#a31515">&quot;&quot;</span>);</pre><pre style="margin:0px">        }</pre><pre style="margin:0px">      }</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:#2b91af">ServiceMetadataBehavior</span> metadataBehavior = <span style="color:blue">new</span> <span style="color:#2b91af">ServiceMetadataBehavior</span>();</pre><pre style="margin:0px">      metadataBehavior.HttpGetEnabled = <span style="color:blue">true</span>;</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      host.Description.Behaviors.Add(metadataBehavior);</pre><pre style="margin:0px"> </pre><pre style="margin:0px">      <span style="color:blue">return</span> host;</pre><pre style="margin:0px">    }</pre><pre style="margin:0px">  }</pre><pre style="margin:0px">}</pre></div></td></tr></tbody></table>Sat, 12 Jul 2008 17:30:18 Z2008-07-12T17:30:18Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#fc20e9f0-1742-439c-9f60-3f4fba19def1http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#fc20e9f0-1742-439c-9f60-3f4fba19def1Jay Kherhttp://social.msdn.microsoft.com/Profile/en-US/?user=Jay%20KherDynamic WCF Services (ASP.NET Virtual Paths) Thanks! this post was helpful.<br><br>JAYTue, 21 Oct 2008 17:19:30 Z2008-10-21T17:20:26Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#0c52aa81-e691-4403-be9f-974181e4807ehttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#0c52aa81-e691-4403-be9f-974181e4807ekainharthttp://social.msdn.microsoft.com/Profile/en-US/?user=kainhartDynamic WCF Services (ASP.NET Virtual Paths)I've been struggling with this same problem for some time now (<font style="font-size:10px">See my post <a href="http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/13c10940-e705-4c7e-8494-b28dac3b95e4/">How do I expose WCF web services in IIS without using .svc files?</a></font>).<br><br><br>I haven't had a chance yet see if I'll be able to use this technique but I'll make sure to respond with the results that I get after I try.<br><br>How has this been working out for you so far and have you run into any problems using this technique? <br><br>Do we sacrifice anything using this technique such as forcing us to host our services within a ASP.NET Web Application or such? I haven't done my homework on the <a href="http://msdn.microsoft.com/en-us/library/system.web.hosting.virtualpathprovider.aspx">VirtualPathProvider </a>class yet so I'm sure I'll be able to answer this myself after digging into a bit. Wed, 12 Nov 2008 14:45:31 Z2008-11-12T14:45:31Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#9b5d3162-c562-4dee-a239-fac5bf2d67e1http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#9b5d3162-c562-4dee-a239-fac5bf2d67e1BinaryCoderhttp://social.msdn.microsoft.com/Profile/en-US/?user=BinaryCoderDynamic WCF Services (ASP.NET Virtual Paths) &gt; How has this been working out for you so far<br><br>I haven't used this in any applications (basically just developed it as an experiment).  So, I can't say.<br>Thu, 13 Nov 2008 12:21:18 Z2008-11-13T12:21:18Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#3b1a066c-101d-460f-afb8-348677b78d69http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#3b1a066c-101d-460f-afb8-348677b78d69kainharthttp://social.msdn.microsoft.com/Profile/en-US/?user=kainhartDynamic WCF Services (ASP.NET Virtual Paths)So far this seems to be working. Of course I also needed to change a few things to fit the goals of my project but the concept of using the VirtualPathProvider to expose virtual .svc files seems to be working like a charm.<br><br>The thing I found interesting was that I needed to use the Global.asax file to initialize my VirtualPathProvider in my WCF Service Application, however from the documentation seems that for projects which are not specifically ASP.NET sites the preference is to use a static AppInitialize method. No matter what I tried the AppInitialize method never seemed to fire for me though so I resorted to using the Global.asax file for now. Furthermore, it doesn't seem possible to add a ASP.NET App_Code folder to my WCF Service Applicatino project. I would have guessed the opposite would have been true.<br>Wed, 26 Nov 2008 21:09:08 Z2008-11-26T21:09:08Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#ecf61056-ea6e-4059-8289-5b616e743e2fhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#ecf61056-ea6e-4059-8289-5b616e743e2fhyspdrthttp://social.msdn.microsoft.com/Profile/en-US/?user=hyspdrtDynamic WCF Services (ASP.NET Virtual Paths)I too have been looking for a solution such as this. I plan on implementing something like this as an HttpHandler or HttpModule listening for *.svc file requests removing the need for the Application_Start implementation. I could then have an independent ServerControl with say a datagrid that could define a request to a Virtual .svc for getting data and whose definition itself would be included in the ServerControl Library. Making the ServerControl Library 100% encapsulated and support dropping into an existing web applicaiton. This would be all ASP.NET/II7. That is the goal anyway. Thanks for the great information!!<br><hr class="sig">hyspdrtWed, 03 Dec 2008 18:54:27 Z2008-12-03T18:54:27Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#a08ec560-6e1f-4c59-a6a1-1a322b9a036bhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#a08ec560-6e1f-4c59-a6a1-1a322b9a036bTyrone Ghttp://social.msdn.microsoft.com/Profile/en-US/?user=Tyrone%20GDynamic WCF Services (ASP.NET Virtual Paths)<p>Thanks this is exactly what I need for a project.</p>Sat, 10 Jan 2009 06:13:11 Z2009-01-10T06:13:11Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#66a83ca0-69c2-4e6a-aed7-5c05207b94e6http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#66a83ca0-69c2-4e6a-aed7-5c05207b94e6Golo Rodenhttp://social.msdn.microsoft.com/Profile/en-US/?user=Golo%20RodenDynamic WCF Services (ASP.NET Virtual Paths) Regarding the HttpModule / HttpHandler - did you succeed?Tue, 17 Mar 2009 16:31:03 Z2009-03-17T16:31:03Zhttp://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#01dcf9c1-286d-4ec2-87a9-ed0a8a22eb53http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/350f2cb6-febd-4978-ae65-f79735d412db#01dcf9c1-286d-4ec2-87a9-ed0a8a22eb53hyspdrthttp://social.msdn.microsoft.com/Profile/en-US/?user=hyspdrtDynamic WCF Services (ASP.NET Virtual Paths) Not exactly, I still use the Virtual Provider in App_Start as that is how ASP.NET Works, but the concept of encapsulating the Wcf/WebService in the UserControl works as long as the NameSpace of your Service matches the Providers lookup NameSpace. This is required for Assembly/Type resolution. I've enhanced slightly to support WebServices and WcfServices.<br> <br>I have no .svc or .asmx files, I create the classes (only) in a Company.Web.Services library or directly in a usercontrol using the same NameSpace. During type resolution the CLR locates the Type by finding the assembly in the bin folder, so the net result is the wcf service is remote or isolated from the main WebApplication Project which merely acts as a general host, and any new or additional usercontrols can be created externally and merely dropped into the bin folder to become available for consumption.<br><br>As an extension to this model, you could create a NamespaceProvider model, where by you register namespaces for virtual services, and the VirtualServiceProvider could look for the requested Service Type using the list of available namespaces. Or store Type definitions in a database, registering &quot;installed&quot; or available Types, so you'd know ahead of time a specific DLL existed and you could look directly in a specific DLL. I have not performed this extension myself but is an idea I'm floating around with.<br><br>Let me know if you have questions as I use this extensively in ASP.NET and Silverlight and works fabulously. The one hitch for .asmx WebServices, is you actually have to have a folder called &quot;Virtual&quot;, even though there is nothing in it. WcfServices do not require this folder.<br><br>Code Snippet...<br><br> <div style="border-bottom:#7f9db9 1px solid;border-left:#7f9db9 1px solid;line-height:100% !important;background-color:white;font-family:Courier New;font-size:11px;overflow:auto;border-top:#7f9db9 1px solid;border-right:#7f9db9 1px solid"> <table style="border-bottom:#eee 0px solid;border-right-width:0px;background-color:#fff;margin:2px 0px;width:99%;border-collapse:collapse;border-top-width:0px;border-left-width:0px" cellspacing=0 cellpadding=0> <colgroup> <col style="border-bottom:#f7f7f7 1px solid;padding-left:10px;font-family:Courier New;white-space:nowrap;font-size:11px"> <tbody> <tr> <td><font style="font-size:11px"></font><font style="color:blue">static</font><font style="font-size:11px"> </font><font style="color:blue">readonly</font><font style="font-size:11px"> </font><font style="color:blue">string</font><font style="font-size:11px"> vdirectoryName = </font><font style="color:blue">&quot;~/Virtual&quot;</font><font style="font-size:11px">;<br>// Hardcoded C# namespace all virtual services must be located in...</font></td></tr> <tr> <td style="background-color:#f7f7f7"></font><font style="color:blue">static</font><font style="font-size:11px"> </font><font style="color:blue">readonly</font><font style="font-size:11px"> </font><font style="color:blue">string</font><font style="font-size:11px"> namespaceName = </font><font style="color:blue">&quot;YourRootNS.Web.Services&quot;</font><font style="font-size:11px">;  </font></td></tr> <tr> <td></font><font style="color:blue">static</font><font style="font-size:11px"> </font><font style="color:blue">readonly</font><font style="font-size:11px"> </font><font style="color:blue">string</font><font style="font-size:11px"> factoryType = </font><font style="color:blue">typeof</font><font style="font-size:11px">(VirtualServiceHostFactory).FullName;  </font></td></tr> <tr> <td style="background-color:#f7f7f7"> </td></tr> <tr> <td></font><font style="color:blue">public</font><font style="font-size:11px"> </font><font style="color:blue">override</font><font style="font-size:11px"> VirtualFile GetFile(</font><font style="color:blue">string</font><font style="font-size:11px"> virtualPath)  </font></td></tr> <tr> <td style="background-color:#f7f7f7">{  </td></tr> <tr> <td>    VirtualFile vfile = </font><font style="color:blue">null</font><font style="font-size:11px">;  </font></td></tr> <tr> <td style="background-color:#f7f7f7"> </td></tr> <tr> <td>    </font><font style="color:blue">string</font><font style="font-size:11px"> appRelativeVirtualPath = </font><font style="color:blue">this</font><font style="font-size:11px">.ToAppRelativeVirtualPath(virtualPath);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">    </font><font style="color:blue">if</font><font style="font-size:11px"> (</font><font style="color:blue">this</font><font style="font-size:11px">.IsVirtualFile(appRelativeVirtualPath))  </font></td></tr> <tr> <td>    {  </td></tr> <tr> <td style="background-color:#f7f7f7">        </font><font style="color:blue">string</font><font style="font-size:11px"> serviceClass = virtualPath;  </font></td></tr> <tr> <td>        serviceClass = VirtualPathUtility.MakeRelative(vdirectoryName + </font><font style="color:blue">&quot;/&quot;</font><font style="font-size:11px">, serviceClass);  </font></td></tr> <tr> <td style="background-color:#f7f7f7"> <table style="border-bottom:#eee 0px solid;border-right-width:0px;background-color:#fff;margin:2px 0px;width:99%;border-collapse:collapse;border-top-width:0px;border-left-width:0px" cellspacing=0 cellpadding=0> <tbody> <tr></tr> <tr></tr></tbody></table>        serviceClass = namespaceName + </font><font style="color:blue">&quot;.&quot;</font><font style="font-size:11px"> + serviceClass;  </font></td></tr> <tr> <td> </td></tr> <tr> <td style="background-color:#f7f7f7">        </font><font style="color:blue">string</font><font style="font-size:11px"> fileExt = Path.GetExtension(virtualPath);  </font></td></tr> <tr> <td>        </font><font style="color:blue">if</font><font style="font-size:11px"> (fileExt == </font><font style="color:blue">&quot;.svc&quot;</font><font style="font-size:11px">)  </font></td></tr> <tr> <td style="background-color:#f7f7f7">        {  </td></tr> <tr> <td>            serviceClass = serviceClass.Substring(0, serviceClass.LastIndexOf(</font><font style="color:blue">&quot;.svc&quot;</font><font style="font-size:11px">));  </font></td></tr> <tr> <td style="background-color:#f7f7f7">            vfile = </font><font style="color:blue">new</font><font style="font-size:11px"> VirtualWCFService(virtualPath, serviceClass, factoryType);  </font></td></tr> <tr> <td>        }  </td></tr> <tr> <td style="background-color:#f7f7f7">        </font><font style="color:blue">else</font><font style="font-size:11px"> </font><font style="color:blue">if</font><font style="font-size:11px"> (fileExt == </font><font style="color:blue">&quot;.asmx&quot;</font><font style="font-size:11px">)  </font></td></tr> <tr> <td>        {  </td></tr> <tr> <td style="background-color:#f7f7f7">            serviceClass = serviceClass.Substring(0, serviceClass.LastIndexOf(</font><font style="color:blue">&quot;.asmx&quot;</font><font style="font-size:11px">));  </font></td></tr> <tr> <td>            Type serviceType = HSS.Reflection.LookupType(serviceClass);  </td></tr> <tr> <td style="background-color:#f7f7f7">            serviceClass += </font><font style="color:blue">&quot;, &quot;</font><font style="font-size:11px"> + serviceType.Assembly.GetName().Name;  </font></td></tr> <tr> <td>            vfile = </font><font style="color:blue">new</font><font style="font-size:11px"> VirtualWebService(virtualPath, serviceClass);  </font></td></tr> <tr> <td style="background-color:#f7f7f7">        }  </td></tr> <tr> <td>    }  </td></tr> <tr> <td style="background-color:#f7f7f7"> </td></tr> <tr> <td>    </font><font style="color:blue">if</font><font style="font-size:11px"> (</font><font style="color:blue">null</font><font style="font-size:11px"> == vfile)  </font></td></tr> <tr> <td style="background-color:#f7f7f7">        vfile = </font><font style="color:blue">this</font><font style="font-size:11px">.Previous.GetFile(virtualPath);  </font></td></tr> <tr> <td> </td></tr> <tr> <td style="background-color:#f7f7f7">    </font><font style="color:blue">return</font><font style="font-size:11px"> vfile;  </font></td></tr> <tr> <td> </td></tr> <tr> <td style="background-color:#f7f7f7">} </td></tr></tbody></table></div><br><hr class="sig">hyspdrtTue, 17 Mar 2009 20:34:47 Z2009-03-17T20:34:47Z