0

我有描述我的合同的 WebGet 和 WebInvoke 属性,但处理无效 URI 的最佳方法是什么?现在,如果用户传递的 URI 与我当前的操作不匹配,他们会得到“找不到端点”。信息。我想回传一个更具描述性的信息。

例如,我的 URI 模板如下所示:

/Stuff/{ID}/subStuff

但说他们打字

/Stuff/{ID}/OtherStuff

没有其他东西这样的东西,我也没有模板。

有没有办法用一个合同覆盖所有非映射的 URI?

谢谢!

4

2 回答 2

1

如果您想在 WCF REST 中在全局级别捕获所有未处理的请求,那么您必须按照本文所述创建自定义WebHttpBehavior定义。IOperationInvoker

如果您想返回带有自定义状态代码(404)的自定义错误文本,您还可以查看此处WebOperationContext.OutgoingResponse描述的属性。

于 2012-06-25T17:39:05.877 回答
1

虽然我确实遵循了提供的链接标记,但它们确实暗示了我需要什么。链接的答案实际上并没有回答我原来的问题。

我能够按照这些步骤进行操作,并且我也想在此问题上列出解决此问题的步骤。

为了创建我自己对未映射到合同中方法的任何 URI 的响应,我创建了以下内容:

  • 自定义 ServiceHostFactory
  • 我在自定义 ServiceHostFactory 中映射到我的端点的行为
  • 一个调度程序,它将处理提供给服务的所有未映射的 uri。

以下是我创建的对象的完整定义:

using System.ServiceModel;
using System.ServiceModel.Activation;

namespace your.namespace.here
{
    public class CustomServiceHostFactory : WebServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
            //note: these endpoints will not exist yet, if you are relying on the svc system to generate your endpoints for you
            // calling host.AddDefaultEndpoints provides you the endpoints you need to add the behavior we need.
            var endpoints = host.AddDefaultEndpoints();
            foreach (var endpoint in endpoints)
            {
                endpoint.Behaviors.Add(new WcfUnkownUriBehavior());
            }

            return host;
        }
    }
}

正如您在上面看到的,我们正在添加一个新行为:WcfUnknownUriBehavior。这个新的自定义行为的核心职责是替换 UnknownDispatcher。下面是那个实现:

using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
namespace your.namespace.here
{
    public class UnknownUriDispatcher : IOperationInvoker
    {
        public object[] AllocateInputs()
        {
            //no inputs are really going to come in,
            //but we want to provide an array anyways
            return new object[1]; 
        }

        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            var responeObject = new YourResponseObject()
            {
                Message = "Invalid Uri",
                Code = "Error",
            };
            Message result = Message.CreateMessage(MessageVersion.None, null, responeObject);
            WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
            outputs = new object[1]{responeObject};
            return result;
        }

        public System.IAsyncResult InvokeBegin(object instance, object[] inputs, System.AsyncCallback callback, object state)
        {
            throw new System.NotImplementedException();
        }

        public object InvokeEnd(object instance, out object[] outputs, System.IAsyncResult result)
        {
            throw new System.NotImplementedException();
        }

        public bool IsSynchronous
        {
            get { return true; }
        }
    }
}

指定这些对象后,您现在可以在 svc 的“标记”中使用新工厂:

<%@ ServiceHost Language="C#" Debug="true" Service="your.service.namespace.here" CodeBehind="myservice.svc.cs"
                Factory="your.namespace.here.CustomServiceHostFactory" %>

应该就是这样。只要您的对象“YourResponseObject”可以被序列化,它的序列化表示就会被发送回客户端。

于 2012-07-19T22:21:46.970 回答