在WCF休息服务中处理404

Jef*_*Pry 5 c# rest wcf exception-handling

我在IIS 7.5上有一个wcf休息服务.当有人访问不存在的端点的一部分时(即http://localhost/rest.svc/DOESNOTEXIST vs http:// localhost/EXISTS),他们会看到一个带有状态代码的Generic WCF灰色和蓝色错误页面404.但是,我想返回如下内容:

<service-response>
   <error>The url requested does not exist</error>
</service-response>
Run Code Online (Sandbox Code Playgroud)

我尝试在IIS中配置自定义错误,但它们仅在请求其余服务之外的页面时才起作用(即http:// localhost/DOESNOTEXIST).

有谁知道如何做到这一点?

编辑 在下面的答案后,我能够弄清楚我需要创建一个实现BehaviorExtensionElement的WebHttpExceptionBehaviorElement类.

 public class WebHttpExceptionBehaviorElement : BehaviorExtensionElement
 {
    ///  
    /// Get the type of behavior to attach to the endpoint  
    ///  
    public override Type BehaviorType
    {
        get
        {
            return typeof(WebHttpExceptionBehavior);
        }
    }

    ///  
    /// Create the custom behavior  
    ///  
    protected override object CreateBehavior()
    {
        return new WebHttpExceptionBehavior();
    }  
 }
Run Code Online (Sandbox Code Playgroud)

然后,我可以通过以下方式在我的web.config文件中引用它:

<extensions>
  <behaviorExtensions>
    <add name="customError" type="Service.WebHttpExceptionBehaviorElement, Service"/>
  </behaviorExtensions>
</extensions>
Run Code Online (Sandbox Code Playgroud)

然后加入

<customError /> 
Run Code Online (Sandbox Code Playgroud)

到我的默认端点行为.

谢谢,

Jeffrey Kevin Pry

Ste*_*eve 5

首先,创建一个子类WebHttpBehavior的自定义行为 - 在这里,您将删除默认的Unhandled Dispatch Operation处理程序,并附加您自己的:

public class WebHttpBehaviorEx : WebHttpBehavior
{
    public override void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        base.ApplyDispatchBehavior(endpoint, endpointDispatcher);

        endpointDispatcher.DispatchRuntime.Operations.Remove(endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation);
        endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation = new DispatchOperation(endpointDispatcher.DispatchRuntime, "*", "*", "*");
        endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.DeserializeRequest = false;
        endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.SerializeReply = false;
        endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.Invoker = new UnknownOperationInvoker();

    }
}
Run Code Online (Sandbox Code Playgroud)

然后.制作未知的操作处理程序.该类将处理未知操作请求并生成作为响应的"消息".我已经展示了如何创建纯文本消息.为您的目的修改它应该是相当直接的:

internal class UnknownOperationInvoker : IOperationInvoker
{
    public object[] AllocateInputs()
    {
        return new object[1];
    }


    private Message CreateTextMessage(string message)
    {
        Message result = Message.CreateMessage(MessageVersion.None, null, new HelpPageGenerator.TextBodyWriter(message));
        result.Properties["WebBodyFormatMessageProperty"] = new WebBodyFormatMessageProperty(WebContentFormat.Raw);
        WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
        return result;
    }

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        // Code HERE

                StringBuilder builder = new System.Text.StringBuilder();

                builder.Append("...");

                Message result = CreateTextMessage(builder.ToString());

                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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

此时,您必须将新行为与您的服务相关联.

有几种方法可以做到这一点,所以只要问你是否还不知道,我将很高兴地进一步阐述.