Skip to content

Instantly share code, notes, and snippets.

@seesharper
Created May 15, 2013 13:43
Show Gist options
  • Save seesharper/5584096 to your computer and use it in GitHub Desktop.
Save seesharper/5584096 to your computer and use it in GitHub Desktop.
Use VirtualPathProvider to feed virtual .svc files to WCF
using System.ServiceModel.Activation;
using System.Web.Hosting;
using System.Web.Routing;
namespace WcfService1.App_Code
{
public static class AppStart
{
public static void AppInitialize()
{
HostingEnvironment.RegisterVirtualPathProvider(
new VirtualSvcPathProvider(
"services", "<%@ ServiceHost Service=\"{0}\" Factory = \"ServiceHostFactoryTypeName\" %>"));
}
}
}
/// <summary>
/// Represents a virtual .svc file.
/// </summary>
public class VirtualSvcFile : VirtualFile
{
private readonly string _content;
/// <summary>
/// Initializes a new instance of the <see cref="VirtualSvcFile"/> class.
/// </summary>
/// <param name="virtualPath">The path to the virtual file.</param>
/// <param name="content">The content of the virtual file.</param>
public VirtualSvcFile(string virtualPath, string content) : base(virtualPath)
{
_content = content;
}
/// <summary>
/// When overridden in a derived class, returns a read-only stream to the virtual resource.
/// </summary>
/// <returns>
/// A read-only stream to the virtual file.
/// </returns>
public override Stream Open()
{
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);
streamWriter.Write(_content);
streamWriter.Flush();
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
}
using System;
using System.IO;
using System.Web;
using System.Web.Hosting;
namespace WcfService1
{
/// <summary>
/// A <see cref="VirtualPathProvider"/> that enables WCF services to be hosted without creating .svc files.
/// </summary>
public class VirtualSvcPathProvider : VirtualPathProvider
{
private readonly string _servicePath;
private readonly string _fileTemplate;
/// <summary>
/// Initializes a new instance of the <see cref="VirtualSvcPathProvider"/> class.
/// </summary>
/// <param name="servicePath">The virtual path to register.</param>
/// <param name="fileTemplate">The svc file template.</param>
public VirtualSvcPathProvider(string servicePath, string fileTemplate)
{
_servicePath = servicePath;
_fileTemplate = fileTemplate;
}
/// <summary>
/// Gets a value that indicates whether a directory exists in the virtual file system.
/// </summary>
/// <returns>
/// true if the directory exists in the virtual file system; otherwise, false.
/// </returns>
/// <param name="virtualDir">The path to the virtual directory.</param>
public override bool DirectoryExists(string virtualDir)
{
return IsPathVirtual(virtualDir) || base.DirectoryExists(virtualDir);
}
/// <summary>
/// Gets a value that indicates whether a file exists in the virtual file system.
/// </summary>
/// <returns>
/// true if the file exists in the virtual file system; otherwise, false.
/// </returns>
/// <param name="virtualPath">The path to the virtual file.</param>
public override bool FileExists(string virtualPath)
{
return IsPathVirtual(virtualPath) || base.FileExists(virtualPath);
}
/// <summary>
/// Gets a virtual file from the virtual file system.
/// </summary>
/// <returns>
/// A descendent of the <see cref="T:System.Web.Hosting.VirtualFile"/> class that represents a file in the virtual file system.
/// </returns>
/// <param name="virtualPath">The path to the virtual file.</param>
public override VirtualFile GetFile(string virtualPath)
{
return new VirtualSvcFile(virtualPath, CreateFileContent(virtualPath));
}
private static string GetServiceName(string virtualPath)
{
return Path.GetFileNameWithoutExtension(virtualPath);
}
private string CreateFileContent(string virtualPath)
{
return string.Format(_fileTemplate, GetServiceName(virtualPath));
}
private bool IsPathVirtual(string virtualPath)
{
string checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return checkPath.StartsWith(string.Format("~/{0}", _servicePath), StringComparison.InvariantCultureIgnoreCase);
}
}
}
@webseb
Copy link

webseb commented Jul 17, 2018

Sorry for nitpicking after 5 years: the VirtualSvcPathProvider must override the GetCacheDependency(string, IEnumerable, DateTime) method (return null for .svc-files) or you will get an error stating that the server "Failed to Start Monitoring Directory Changes". Got the hint from a question on StackOverflow. Thx for the sample!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment