You can do it programmatically, but I'm believe the way to do it is not good for production environment. Implementation of HelpPage hidden by Microsoft in System.ServiceModel.Web.dll and there's no extensibility points to change this behavior.
But we know current implementation and we can use reflection to implement dynamic managing of methods for HelpPage. But contract and implementation details can be changed by MS and our implementation will be broken. So, I'm strongly don't recommend to use it in a real environment.
Here's a custom BadCustomHelpPageWebHttpBehavior (inherited from WebHttpBehavior). Constructor takes an array of methods to exclude from Help Page:
public class BadCustomHelpPageWebHttpBehavior : WebHttpBehavior
{
/// <summary>
/// Creates BadCustomHelpPageWebHttpBehavior
/// </summary>
/// <param name="ignoredMethodNames">Array of method names to ignore in Help Page</param>
public BadCustomHelpPageWebHttpBehavior(string[] ignoredMethodNames)
{
m_ignoredMethodNames = ignoredMethodNames;
}
/// <summary>
/// Remove methods to display in Help Page by names passed in the constructor
/// </summary>
public override void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
base.ApplyDispatchBehavior(endpoint, endpointDispatcher);
if (m_ignoredMethodNames == null || m_ignoredMethodNames.Length == 0)
return;
DispatchOperation helpOperation = endpointDispatcher.DispatchRuntime.Operations.FirstOrDefault(o => o.Name == "HelpPageInvoke");
if(helpOperation == null)
return;
IOperationInvoker helpInvoker = helpOperation.Invoker;
Type helpInvokerType = CreateInternalSystemServiceWebType("System.ServiceModel.Web.HelpOperationInvoker");
FieldInfo helpPageFieldInfo = helpInvokerType.GetField("helpPage",
BindingFlags.Instance | BindingFlags.NonPublic);
if (helpPageFieldInfo != null)
{
object helpPage = helpPageFieldInfo.GetValue(helpInvoker);
Type helpPageType = CreateInternalSystemServiceWebType("System.ServiceModel.Dispatcher.HelpPage");
Type operationHelpInformationType =
CreateInternalSystemServiceWebType("System.ServiceModel.Dispatcher.OperationHelpInformation");
Type dictionaryType = typeof (Dictionary<,>);
Type[] operationInfoDictionaryGenericTypes = {typeof (string), operationHelpInformationType};
Type operationInfoDictionaryType = dictionaryType.MakeGenericType(operationInfoDictionaryGenericTypes);
FieldInfo operationInfoDictionaryFieldInfo = helpPageType.GetField("operationInfoDictionary",
BindingFlags.Instance | BindingFlags.NonPublic);
if (operationInfoDictionaryFieldInfo != null)
{
object operationInfoDictionary = operationInfoDictionaryFieldInfo.GetValue(helpPage);
object operationInfoDictionaryReplaced = RemoveHelpMethods(operationInfoDictionary,
operationInfoDictionaryType);
operationInfoDictionaryFieldInfo.SetValue(helpPage, operationInfoDictionaryReplaced);
}
}
}
private object RemoveHelpMethods(object operationInfoDictionary, Type operationInfoDictionaryType)
{
Debug.Assert(m_ignoredMethodNames != null);
var operationInfoDictionaryReplaced = Activator.CreateInstance(operationInfoDictionaryType);
var operationInfoDictionaryAsEnumerable = operationInfoDictionary as IEnumerable;
if (operationInfoDictionaryAsEnumerable != null)
{
foreach (var operationInfoEntry in operationInfoDictionaryAsEnumerable)
{
object key = operationInfoEntry.GetType().GetProperty("Key").GetValue(operationInfoEntry);
object value = operationInfoEntry.GetType().GetProperty("Value").GetValue(operationInfoEntry);
string name = value.GetType().GetProperty("Name").GetValue(value) as string;
if (m_ignoredMethodNames.Contains(name) == false)
{
operationInfoDictionaryReplaced.GetType()
.GetMethod("Add")
.Invoke(operationInfoDictionaryReplaced, new[] {key, value});
}
}
}
return operationInfoDictionaryReplaced;
}
private static Type CreateInternalSystemServiceWebType(string requestedType)
{
return typeof (WebServiceHost).Assembly.GetType(requestedType);
}
private readonly string[] m_ignoredMethodNames;
}
To use this class just add this behavior to you endpoint:
host.Description.Endpoints[0].Behaviors.Add(new BadCustomHelpPageWebHttpBehavior(new[] { "EchoWithGet" })
{
HelpEnabled = true
});
Full source code of this example including simple WCF HTTP server could be found here:
https://github.com/knyu15/BadCustomHelpPageWebHttpBehavior
Possible the better way is to replace WCF HelpPage with your custom page. Detailed example could be found here:
Customize the WebHttp Help Output in WCF. But this is not answering your immediate question, though.