Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在WCF Rest服务中处理404_C#_Wcf_Rest_Exception Handling - Fatal编程技术网

C# 在WCF Rest服务中处理404

C# 在WCF Rest服务中处理404,c#,wcf,rest,exception-handling,C#,Wcf,Rest,Exception Handling,我在IIS 7.5上有一个wcf rest服务。当有人访问不存在的端点部分(即vs)时,他们将看到一个通用的WCF灰色和蓝色错误页面,状态代码为404。但是,我想返回如下内容: <service-response> <error>The url requested does not exist</error> </service-response> 然后,我可以通过以下方式在我的web.config文件中引用它: <extension

我在IIS 7.5上有一个wcf rest服务。当有人访问不存在的端点部分(即vs)时,他们将看到一个通用的WCF灰色和蓝色错误页面,状态代码为404。但是,我想返回如下内容:

<service-response>
   <error>The url requested does not exist</error>
</service-response>
然后,我可以通过以下方式在我的web.config文件中引用它:

<extensions>
  <behaviorExtensions>
    <add name="customError" type="Service.WebHttpExceptionBehaviorElement, Service"/>
  </behaviorExtensions>
</extensions>

然后加上

<customError /> 

我的默认端点行为

谢谢


Jeffrey Kevin Pry

首先,创建一个自定义行为,将WebHttpBehavior子类化-在这里,您将删除默认的未处理分派操作处理程序,并附加您自己的:

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();

    }
}
那么。使您的未知操作处理程序。此类将处理未知的操作请求并生成一条“消息”,即响应。我已经演示了如何创建纯文本消息。为您的目的修改它应该相当简单:

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; }
    }
}
此时,您必须将新行为与服务相关联


有几种方法可以做到这一点,所以只要问问你是否还不知道,我很乐意进一步详细说明

我有一个类似的问题,而另一个答案确实导致了我最终的成功,这不是最清晰的答案。下面是我解决这个问题的方法

“我的项目”设置是一个WCF服务,作为托管在IIS中的svc托管。我无法按照配置路径添加行为,因为由于持续集成,我的程序集版本每次签入都会更改

为了克服这一障碍,我创建了一个自定义ServiceHostFactory:

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;
        }
    }
}
正如您在上面看到的,我们正在添加一个新行为:wcfunnownuribehavior。这种新的习俗行为的灵魂职责是取代未知的习俗。以下是执行情况:

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的“标记”中使用新工厂:



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

是否使用REST Starter kit或WCF Web API?在调用部分,我应该为输入和输出分配什么?我在配置中将Web行为关联到哪里?这就是我现在拥有的。。。谢谢你的帮助!我将更详细地更新答案,关于:您的注释——但简而言之,请参见如何在invoke方法中“返回结果;”?它正在返回一种“消息”。。。这就是你想要的。此链接:包含使用web配置添加新客户行为的说明。谢谢。。。但是在invoke方法中,您也有out object[]输出作为参数。它不允许我返回空输出。我正在回信。我将等待您对关联行为的实现回复。再次感谢您的帮助!很抱歉,我上班时被狠狠揍了一顿。。。很高兴你明白了。哈哈。。。你发布了一个与一年前不同的答案,然后否决了我的答案?好吧,我想。哎呀。很抱歉我不是有意否定你的答案。我一定是摸到它了。我道歉。
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; }
        }
    }
}
<%@ ServiceHost Language="C#" Debug="true" Service="your.service.namespace.here" CodeBehind="myservice.svc.cs"
                Factory="your.namespace.here.CustomServiceHostFactory" %>