How do I restrict the content of stack trace to Client of Web Service in ASP.Net

TariqAdib
 
on Apr 05, 2016 03:37 AM
Sample_794102.zip
2903 Views

A desktop application I am working on consumes certain web services. The problem here is that if an exception is raised in the service method, the stack trace is propagated to the application and the stack trace shows the name of the method that throws the exception. I want to hide this from the user or preferably hide the stack trace entirely. Is there someway to do this without extending the exception class? 

 

I'm using traditional .web services, not WCF.

Download FREE API for Word, Excel and PDF in ASP.Net: Download
Shashikant
 
on Apr 07, 2016 04:39 AM

Here I have created sample that will help you out.

I have make use of custom Attribute

FewService(WebService)

[WebMethod]
// Use Parameterized GlobalErrorHandler to Specify Error Discription.
[GlobalServiceErrorHandler("Divide operation Mathmatical Error")]
public double Divide(int numerator, int denominator)
{
    try
    {
        return numerator / denominator;
    }
    catch (Exception e)
    {
        throw new GlobalErrorHandler(e).faultException;
    }
}

[WebMethod]
// Parameterless GlobalErrorHandler throws General Error Discription.
[GlobalServiceErrorHandler]
public byte[] GetFileContent(string path)
{
    try
    {
        return File.ReadAllBytes(path);
    }
    catch (Exception e)
    {
        throw new GlobalErrorHandler(e).faultException;
    }
}

GlobalServiceErrorHandlerAttribute(Class)

public class GlobalServiceErrorHandlerAttribute : Attribute
{
    public GlobalServiceErrorHandlerAttribute()
    {
        this.Description = "General Exception";
    }
    public GlobalServiceErrorHandlerAttribute(string description)
    {
        this.Description = description;
    }
    public string Description { get; set; }
}

GlobalErrorHandler

public class GlobalErrorHandler
{
    public readonly FaultException faultException;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="e"></param>
    public GlobalErrorHandler(Exception e)
    {
        this.faultException = GetFaultedException(e);
    }

    /// <summary>
    /// Frame the detail message from exception
    /// </summary>
    /// <param name="ex"></param>
    /// <returns></returns>
    public static FaultException GetFaultedException(Exception ex)
    {
        if (ex is FaultException)
            return ex as FaultException;

        StringBuilder messageBuilder = new StringBuilder();
        Type attributeType = typeof(GlobalServiceErrorHandlerAttribute);
        int step = 1;

        var attributes = GetStackTraceSteps<GlobalServiceErrorHandlerAttribute>(ex);
        if (attributes != null && attributes.Count > 0)
            messageBuilder.AppendLine(string.Format
            ("Sorry there is a problem while processing step {0}:", attributes.Count));
        foreach (var attribute in attributes)
        {
            messageBuilder.Append(string.Format
            ("Step {0}: {1}", step.ToString(), attribute.Description));
            messageBuilder.AppendLine();
            step++;
        }
        messageBuilder.AppendLine();

        string formatedMessage = string.Format("{0}", messageBuilder.ToString());
        return new FaultException(formatedMessage);
    }

    /// <summary>
    /// Extrace the custom attribute details from the stacktrace
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="ex"></param>
    /// <returns></returns>
    public static List<T> GetStackTraceSteps<T>(Exception ex)
    {
        List<T> traceSteps = new List<T>();
        Type attributeType = typeof(T);
        StackTrace st = new StackTrace(ex);
        if (st != null && st.FrameCount > 0)
        {

            for (int index = st.FrameCount - 1; index >= 0; index--)
            {
                var attribute = st.GetFrame(index).
                GetMethod().GetCustomAttributes(attributeType, false).FirstOrDefault();
                if (attribute != null)
                {
                    traceSteps.Add((T)attribute);
                }
            }
        }
        return traceSteps;
    }
}

Default.aspx(Dividision Calculation)

<div>
    <table border="0" cellpadding="0" cellspacing="0">
        <tr>
            <td>
                Numerator:
            </td>
            <td>
                <asp:TextBox ID="txtNumerator" runat="server" />
            </td>
        </tr>
        <tr>
            <td>
                Denominator:
            </td>
            <td>
                <asp:TextBox ID="txtDenominator" runat="server" />
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:Button Text="Divide" runat="server" OnClick="Divide" />
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:Label ID="lblResult" runat="server" />
            </td>
        </tr>
    </table>
</div>

 C#

protected void Divide(object sender, EventArgs e)
{
    FewService.FewServiceSoapClient client = new FewService.FewServiceSoapClient();
    lblResult.Text = client.Divide(Convert.ToInt32(txtNumerator.Text), Convert.ToInt32(txtDenominator.Text)).ToString();
}

ReadFile.aspx(Read File Content)

<div>
    Enter FilePath:<asp:TextBox ID="txtFilePath" runat="server" />
    <asp:Button Text="Read" runat="server" OnClick="ReadFileContent" />
</div>

C#

protected void ReadFileContent(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(txtFilePath.Text))
    {
        FewService.FewServiceSoapClient client = new FewService.FewServiceSoapClient();
        client.GetFileContent(txtFilePath.Text);
    }
}

Screenshot