Created
May 15, 2013 13:43
-
-
Save seesharper/5584096 to your computer and use it in GitHub Desktop.
Use VirtualPathProvider to feed virtual .svc files to WCF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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\" %>")); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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!