Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
188 views
in Technique[技术] by (71.8m points)

c# - Format stack trace to manually return in API response

Currently it is returning a single unintelligible chunk composed of multiple of these things glued one next to the other like this:

at ProyectX.Services.Service.Validate(IList 1 myParam) in C:\Repositories\projectx\src\ProyectX.Services\Service.cs:line 116 at ProyectX.Services.Service.Validate(IList 1 myParam) in C:\Repositories\projectx\src\ProyectX.Services\Service.cs:line 116

Goal:

at ProyectX.Services.Service.Validate(IList 1 myParam) in C:RepositoriesprojectxsrcProyectX.ServicesService.cs:line 116

at ProyectX.Services.Service.Validate(IList 1 myParam) in C:RepositoriesprojectxsrcProyectX.ServicesService.cs:line 116

I tried with

Regex.Unescape(exception.StackTrace)

JsonSerializer.Serialize(exception.StackTrace, new JsonSerializerOptions() {WriteIndented = true });

The middleware is in Startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseMiddleware<ErrorHandlerMiddleware>();

Middleweare:

using System;
using System.Collections.Generic;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using ProyectX.Domain.Exceptions;
using ProyectX.Domain.Models;

namespace ProyectX.API.Middleware
{
    public class ErrorHandlerMiddleware
    {
        private readonly RequestDelegate _next;

        public ErrorHandlerMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context, IWebHostEnvironment env)
        {
            try
            {
                await _next(context);
            }
            catch (Exception exception)
            {
                var response = context.Response;
                response.ContentType = "application/json";

                switch (exception)
                {
                    case InvalidOperationException:
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        break;
                    default:
                        response.StatusCode = (int)HttpStatusCode.InternalServerError;
                        break;
                }

                var details = new Dictionary<string, string>
                {
                    { "Message", exception.Message },
                };

                if (env.IsDevelopment())
                {
                    details.Add("StackTrace", exception.StackTrace);
                }

                var errorResponse = new ErrorResponseModel(exception, details);
                var result = JsonSerializer.Serialize(errorResponse);

                await response.WriteAsync(result);
            }
        }
    }
}

ErrorResponseModel

using System;
using System.Collections.Generic;

namespace ProyectX.Domain.Models
{
    public class ErrorResponseModel
    {
        public ErrorResponseModel(Exception ex, Dictionary<string, string> details)
        {
            Type = ex.GetType().Name;
            Details = details;
        }

        public string Type { get; set; }

        public IDictionary<string, string> Details { get; set; }
    }
}
question from:https://stackoverflow.com/questions/65830407/format-stack-trace-to-manually-return-in-api-response

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I would suggest changing a bit in your ErrorResponseModel class so that your dictionary accept object type as value, like Dictionary<string, object>. Here comes the idea, that you can both added string OR string array.

So for your tacktrace, you can split it multiple line using split by " " and get a string array of it, that I can pass to my StackTrace value.

So lets come to your model:

public class ErrorResponseModel
{
    public ErrorResponseModel(Exception ex, Dictionary<string, object> details)
    {
        Type = ex.GetType().Name;
        Details = details;
    }

    public string Type { get; set; }

    public IDictionary<string, object> Details { get; set; }
}

Here is the part that handle exception:

var details = new Dictionary<string, object>
{
    { "Message", exception.Message} ,
};

var lines = exception.StackTrace?.Split("
").Select(e => e.TrimStart());
details.Add("StackTrace", lines);

var errorResponse = new ErrorResponseModel(exception, details);

var result = JsonSerializer.Serialize(errorResponse, new JsonSerializerOptions() { WriteIndented = true });

All this return following out:

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...