.net 是否以编程方式从WCF Web HTTP服务帮助页中删除方法?

.net 是否以编程方式从WCF Web HTTP服务帮助页中删除方法?,.net,wcf,.net,Wcf,如何以编程方式从中删除服务方法?我仍然希望显示帮助页面,但我需要从中删除特定的方法,而不更改ServiceContract 我已尝试通过自定义IEndpointBehavior从ServiceEndpoints中删除服务方法,如下所示: public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { var operations

如何以编程方式从中删除服务方法?我仍然希望显示帮助页面,但我需要从中删除特定的方法,而不更改ServiceContract

我已尝试通过自定义IEndpointBehavior从ServiceEndpoints中删除服务方法,如下所示:

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        var operationsToRemove = endpointDispatcher.DispatchRuntime.Operations.Where(op => this.IsDeprecated(op)).ToList();
        foreach (var operation in operationsToRemove)
        {
            endpointDispatcher.DispatchRuntime.Operations.Remove(operation);
        }
    }
。。。当调用一个不推荐的方法时,我会得到一个“methodnotallowed”错误(根据需要)


我还尝试按照中的步骤从WSDL/自动生成的客户机中省略服务方法,但这似乎不会影响帮助页面。

您可以通过编程方式完成,但我相信这种方式不适合生产环境。Microsoft在System.ServiceModel.Web.dll中隐藏帮助页的实现,并且没有可扩展性点来更改此行为

但是我们知道当前的实现,我们可以使用反射来实现HelpPage方法的动态管理。但MS可以更改合同和实施细节,我们的实施将被破坏。因此,我强烈建议不要在真实环境中使用它

下面是一个自定义的BadCustomHelpPageWebHttpBehavior(继承自WebHttpBehavior)。构造函数从帮助页中排除一组方法:

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;
}
此示例的完整源代码(包括简单WCF HTTP服务器)可在此处找到:

可能更好的方法是用自定义页面替换WCF帮助页面。详细示例可在此处找到:
. 但这并不能回答您当前的问题。

您可以在web.config文件中更改此行为。这就是你要找的吗?@Steve,我仍然希望帮助页面出现。我希望删除/隐藏ServiceContract中的特定方法。(我将更新问题,使其更加清晰。)它工作得非常完美。谢谢感谢您提供更多“更正确”的答案/链接。:)
host.Description.Endpoints[0].Behaviors.Add(new BadCustomHelpPageWebHttpBehavior(new[] { "EchoWithGet" })
{
    HelpEnabled = true
});