首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WCF FaultContract在NamedPipe中失败

WCF FaultContract在NamedPipe中失败
EN

Stack Overflow用户
提问于 2011-02-03 16:25:11
回答 1查看 1.9K关注 0票数 1

我有一个简单的IPC机制,它使用WCF和命名管道。我的目标是将异常细节(包括堆栈跟踪)传播到客户端,以便进行日志记录(应用程序日志的其余部分位于客户机上)。

如果我使用以下代码,我就能够在客户机上捕获FaultException并查看异常详细信息:

合同:

代码语言:javascript
复制
[ServiceContract]
public interface IService
{
    [OperationContract]
    [FaultContract(typeof(Exception))]
    void DoSomething();
}

执行情况:

代码语言:javascript
复制
public class Service : IService
{
    public void DoSomething()
    {
        try
        {
            ThisWillThrowAnException();
        }
        catch (Exception e)
        {
            throw new FaultException<Exception>(e);
        }
    }
 }

客户端:

代码语言:javascript
复制
public void CallServer()
{
    try
    {
        proxy.DoSomething();
    }
    catch (FaultException<Exception> e)
    {
        Console.WriteLine("Caught fault exception!");
    }
}

这很好,我看到控制台上打印的消息。但是,如果我想使用我自己的派生异常而不是基本异常类,它将失败。

自定义例外:

代码语言:javascript
复制
[Serializable]
public class MyException : Exception
{
    public MyException () { }
    public MyException (string message) : base(message) { }
    public MyException (string message, Exception inner) : base(message, inner) { }
    protected MyException (
      SerializationInfo info,
      StreamingContext context)
        : base(info, context) { }
}

将FaultContract on IService.DoSomething更改为

代码语言:javascript
复制
typeof(MyException).

将“服务中的抛出”子句更改为

代码语言:javascript
复制
new FaultException<MyException>(new MyException(e.Message, e);

将客户端的catch子句更改为

代码语言:javascript
复制
catch (FaultException<MyException> e)

当我执行此操作时,会在客户机上捕获一个CommunicationException,错误为: System.ServiceModel.CommunicationException:从管道读取错误:管道已经结束。(109,0x6d)。

MyException类位于对客户端和服务器都可用的共享库中。

这个问题非常类似于this question,但这并没有帮助我。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-02-04 18:43:54

我通过编写我自己的错误DataContract来解决这个问题,它包含了一个序列化的StackFrames列表。

很明显,这篇MSDN文章并不准确?

http://msdn.microsoft.com/en-us/library/ff649840.aspx

代码语言:javascript
复制
[DataContract]
public class MyFault
{
    [DataMember]
    public string Message { get; set; }

    [DataMember]
    public IList<SerializableMiniStackFrame> StackTrace { get; set; }


    public static MyFault CreateFault(Exception e)
    {
        MyFault fault = new MyFault();
        fault.Message = e.Message;
        fault.InitTrace(e);
        return fault;
    }

    /// <summary>
    /// Initializes the stack trace based on when the inner exception was thrown.
    /// </summary>
    /// <param name="inner">The inner exception.</param>
    private void InitTrace(Exception inner)
    {
        StackTrace trace = new StackTrace(inner, true);
        InitTrace(trace);
    }

    /// <summary>
    /// Initializes the internal serializable stack frames based on the given
    /// stack trace.
    /// </summary>
    /// <param name="stackTrace">The stack trace.</param>
    private void InitTrace(StackTrace stackTrace)
    {
        // Create a new list of serializable frames.
        this.StackTrace = new List<SerializableMiniStackFrame>();
        // Iterate over each frame in the stack trace.
        foreach (StackFrame frame in stackTrace.GetFrames())
        {
            string type = "";
            Type declaringType = frame.GetMethod().DeclaringType;
            if (null != declaringType)
            {
                type = declaringType.FullName;
            }

            MethodBase method = frame.GetMethod();
            string methodName = method.Name;
            string parameters = string.Empty;
            string delimiter = string.Empty;
            foreach (ParameterInfo parameter in method.GetParameters())
            {
                parameters += string.Format("{0}{1} {2}", delimiter, parameter.ParameterType.Name, parameter.Name);
                delimiter = ", ";
            }
            string file = Path.GetFileName(frame.GetFileName());
            int line = frame.GetFileLineNumber();

            // Create a serializable frame and add it to the list.
            SerializableMiniStackFrame miniFrame = new SerializableMiniStackFrame(type, methodName, parameters, file, line);
            this.StackTrace.Add(miniFrame);
        }
    }
}

/// <summary>
/// This class encapsulates basic stack frame information into a serializable
/// object.
/// </summary>
[DataContract]
public class SerializableMiniStackFrame
{
    public SerializableMiniStackFrame() { }
    public SerializableMiniStackFrame(string type, string method, string parameters, string file, int line)
    {
        this.Type = type;
        this.Method = method;
        this.Parameters = parameters;
        this.File = file;
        this.Line = line;
    }

    [DataMember]
    public string Type { get; set; }
    [DataMember]
    public string Method { get; set; }
    [DataMember]
    public string Parameters { get; set; }
    [DataMember]
    public string File { get; set; }
    [DataMember]
    public int Line { get; set; }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4888713

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档