8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

使用自定义类在 Azure 函数中处理错误

garish 3月前

82 0

我的登录功能如下所示:[Function(\'Loginxyz\')]public async Task生成令牌([HttpTrigger(AuthorizationLevel.Anonymous,\'post\',路线=&

我的登录功能如下所示:

[Function("Loginxyz")]
public async Task<IActionResult> GenerateToken(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "user/login")] HttpRequestData req,
        ILogger log)
{
    try
    {
        if (requestData.BarCode != null)
        {
            var localLoginRequest = JsonConvert.DeserializeObject<xyz>(requestBody);
            token = await _tokenService.GenerateToken(localLoginRequest);
        }

        if (token == null)
            return new UnauthorizedResult();

        return new OkObjectResult(new { access_token = token });
    }
    catch (AggregateException ae)
    {
        // Handle multiple exceptions
        foreach (var innerException in ae.InnerExceptions)
        {
            log.LogError(innerException, "An error occurred");
            // Handle the inner exception based on its type
        }

        // Return a specific error response based on the aggregate exception
        return new BadRequestObjectResult("An error occurred");
    }
    catch (AuthenticationServiceException ex)
    {
        // Log the error with detailed message
        log.LogError($"Error during token generation: {ex.Message}", ex);

        // Create a custom error response object
        var errorResponse = new
            {
                Error = ex.Message,
                StatusCode = StatusCodes.Status400BadRequest
            };

        // Return the error response with the appropriate status code
        return new JsonResult(errorResponse) { StatusCode = StatusCodes.Status400BadRequest };
    }
    catch (LoginConflictException ex)
    {
        // Log the error with detailed message
        log.LogError($"Error during token generation: {ex.Message}", ex);

        // Create a custom error response object
        var errorResponse = new
            {
                Error = ex.Message,
                StatusCode = StatusCodes.Status409Conflict
            };

        // Return the error response with the appropriate status code
        return new JsonResult(errorResponse) { StatusCode = StatusCodes.Status409Conflict };
    }
    catch (Exception ex)
    {
        log.LogError($"Error during token generation: {ex.Message}");
        return new StatusCodeResult(StatusCodes.Status500InternalServerError);
    }
}

我的服务类如下所示:

public async Task<TokenResponseDto> GenerateToken(object tokenRequest)
{
    try
    {
        return await tokenGenerator.GenerateToken(tokenRequest);
    }
    catch (Exception ex)
    {
        throw; // Rethrow the exception
    }
}

异常跟踪:- Function 'Login', Invocation id '': An exception was thrown by the invocation. [2024-07-13T02:28:21.903Z] Result: Function 'Login', Invocation id '': An exception was thrown by the invocation. Exception: System.ArgumentNullException: Value cannot be null. (Parameter 'logger') [2024-07-13T02:28:21.903Z] at System.ThrowHelper.Throw(String paramName) [2024-07-13T02:28:21.904Z] at Microsoft.Extensions.Logging.LoggerExtensions.Log(ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, String message, Object[] args) [2024-07-13T02:28:21.904Z] at Microsoft.Extensions.Logging.LoggerExtensions.LogError(ILogger logger, String message, Object[] args) [2024-07-13T02:28:21.905Z] at ..AzureFunctions.Funtions.User.LoginFunction.GenerateToken(HttpRequestData req, ILogger log) in \Funtions\User\LoginFunction.cs:line 86 [2024-07-13T02:28:21.907Z] at ..DirectFunctionExecutor.ExecuteAsync(FunctionContext context) in ..\Microsoft.Azure.Functions.Worker.Sdk.Generators\Microsoft.Azure.Functions.Worker.Sdk.Generators.FunctionExecutorGenerator\GeneratedFunctionExecutor.g.cs:line 38 [2024-07-13T02:28:21.909Z] at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 13 [2024-07-13T02:28:21.909Z] at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 48 [2024-07-13T02:28:21.910Z] at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 89 Stack: at System.ThrowHelper.Throw(String paramName) [2024-07-13T02:28:21.911Z] at Microsoft.Extensions.Logging.LoggerExtensions.Log(ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, String message, Object[] args) [2024-07-13T02:28:21.912Z] at Microsoft.Extensions.Logging.LoggerExtensions.LogError(ILogger logger, String message, Object[] args) [2024-07-13T02:28:21.915Z] at ..Funtions.User.LoginFunction.GenerateToken(HttpRequestData req, ILogger log) in .\Funtions\User\LoginFunction.cs:line 86 [2024-07-13T02:28:21.916Z] at ..DirectFunctionExecutor.ExecuteAsync(FunctionContext context) in ..\Microsoft.Azure.Functions.Worker.Sdk.Generators\Microsoft.Azure.Functions.Worker.Sdk.Generators.FunctionExecutorGenerator\GeneratedFunctionExecutor.g.cs:line 38 [2024-07-13T02:28:21.917Z] at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 13 [2024-07-13T02:28:21.918Z] at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 48 [2024-07-13T02:28:21.919Z] at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 89. [2024-07-13T02:28:58.728Z] Executed 'Functions.Login' (Failed, Id=b4005c4b-a335-46f7-8dc7-cf24b1d62fe7, Duration=48071ms) [2024-07-13T02:28:58.730Z] System.Private.CoreLib: Exception while executing function: Functions.Login. Microsoft.Azure.WebJobs.Script.Grpc: Failed to proxy request with ForwarderError: RequestCanceled. System.Net.Http: The operation was canceled. System.Net.Sockets: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request.. The I/O operation has been aborted because of either a thread exit or an application request.

我在方法中抛出错误 tokenGenerator.GenerateToken ,然后在服务类中重新抛出该错误。我的预期是,当我在服务类中重新抛出错误时,它应该在我的 Azure 函数中被捕获,但这并没有发生。

但是,我从重新抛出中得到的错误是:

调用引发了异常。
异常:System.ArgumentNullException:值不能为空。(参数“logger”)

我已经在我的 cmd 日志中捕获了此信息。

这很令人困惑,因为我抛出了一个自定义错误,与 ArgumentNullException .

有人能帮助我理解这一点吗?

帖子版权声明 1、本帖标题:使用自定义类在 Azure 函数中处理错误
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由garish在本站《asp.net》版块原创发布, 转载请注明出处!
最新回复 (0)
  • logger) { _logger = logger ?? 抛出新的 ArgumentNullException(nameof(logger)); }@PeterBons 我联系记录器就像私人只读 ILogger_logger; 公共登录函数(ILogger

  • 我有一个这样的结构:typedef struct { int row; int col; double *entries;} Matrix;我想编写函数来创建、释放等。例如:Matrix *mtalloc(typeof((Matrix) {}.row)...

    我有一个像这样的结构:

    typedef struct {
        int row;
        int col;
        double *entries;
    } Matrix;
    

    我想要编写函数来创建、释放等等。例如:

    Matrix *mtalloc(typeof((Matrix) {}.row) row, typeof((Matrix) {}.col) col)
    {
        Matrix *p = malloc(sizeof(Matrix));
    
        if (p == NULL) {
            fprintf(stderr, "mtalloc(%x, %x): malloc returned NULL\n", row, col);
            exit(EXIT_FAILURE);
        }
    
        p->row = row;
        p->col = col;
        p->entries = malloc(sizeof(*((Matrix) {}.entries)) * row * col);
        return p;
    }
    

    这样,如果结构体中字段的类型发生变化,函数就不需要改变,但这是好的还是坏的做法?

  • 意见问题。在我看来,更明显的错误做法是函数调用 malloc 两次,而实际上只需调用一次即可。

  • typeof 是一个很酷的技巧,但这些函数是 Matrix 接口的一部分。您认为 row 和 col 的类型有多大可能发生变化?如果不是“非常”,那么您只是让代码变得过于复杂,而一个简单的搜索和替换过程就可以解决问题,如果需要进行 ABI 破坏类型的更改。(请记住,使用代码也需要更新。)最好现在就决定硬限制。实际上,int 应该足以索引您可以放入内存中的任何密集矩阵。

  • @Dúthomhas 消除第一个 malloc 会引入一些调整大小的问题。要么你把整个东西分配到一个块中,然后让调整大小函数接受一个

  • Luca 3月前 0 只看Ta
    引用 7

    这段代码的质量值得怀疑,因为它不必要地使用了花哨的功能,而且需要复杂的标点符号(圆括号、大括号等)。有一种更好的方法是使用 C 中长期存在的功能:

    typedef int MatrixRowT;
    typedef int MatrixColT;
    
    typedef struct {
        MatrixRowT row;
        MatrixColT col;
        double *entries;
    } Matrix;
    
    
    Matrix *mtalloc(MatrixRowT row, MatrixColT col)
    …
    

    row 的类型 col 只需在一个地方更改代码。但是,它更易于阅读。

    如果 row 预计 col

    此代码:

        p->entries = malloc(sizeof(*((Matrix) {}.entries)) * row * col);
    

    不需要复合文字;它可以简单地是:

        p->entries = malloc(sizeof *p->entries * row * col);
    

    还应该有文档说明该函数的作用 mtalloc 、传递的参数值的约束以及如何释放它分配的内存。第二个函数中还应该有一个失败测试 malloc .

  • 既然 OP 对结构的大小没有要求,为什么不使用特定大小的类型 size_t?对我来说,用其他类型来输入大小总是一种代码异味。

  • 尝试学习 C 的细微差别,尽管我做得很好,直到我发现这个:#define SOKOL_IMPL#define SOKOL_GLES3#include \'sokol_gfx.h\'#include \'sokol_log.h\'#include "...

    尝试学习 C 的细微差别,尽管我做得很好,直到我发现这一点:

    #define SOKOL_IMPL
    #define SOKOL_GLES3
    #include "sokol_gfx.h"
    #include "sokol_log.h"
    #include "emsc.h"
    
    static struct {
        sg_pipeline pip;
        sg_bindings bind;
        sg_pass_action pass_action;
    } state = {
        .pass_action.colors[0] = { .load_action = SG_LOADACTION_CLEAR, .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f } }
    };
    

    这是来自 Sokol 库的示例代码: https://github.com/floooh/sokol-samples/blob/master/html5/triangle-emsc.c

    我知道第一个结构声明也声明了一个变量“state”,然后我认为这个新变量被使用“指定的 init”分配给“=”之后的任何内容。我不明白 .pass_action.colors[0] 是什么。

    我以为 \'colors\' 是 pass_action 中的一个字段,这反过来又使 pass action 成为一个结构体,而 colors 应该是一个数组。但是,\'colors\' 赋值再次使用指定的 init 惯用结构体。

    因此,也许 .colors[0] 是 .pass_action 的一个字段,也是一个结构数组,它有两个字段:“load_action”和“clear_value”。对吗?我需要先确定,然后才能继续。

    \'指定初始化\': https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

    上方几行定义 https://github.com/floooh/sokol/blob/6f8121e6aa523b0c0a3e9d7212073bab9a885e15/sokol_gfx.h#L2542

    reddit 上其他地方已经有人向我指出了这一点,并澄清了所有问题(我认为)。\'colors\' 是 \'sg_color_attachment_action\' 类型的数组,其本身是一个结构。大小为 \'SG_MAX_COLOR_ATTACHMENTS\'。

  • 谢谢大家 : ) 我自己检查了标题,但仍然不确定,因为我刚刚学习这个。这与我习惯的非常不同。我认为这已经得到证实,有人(在 reddit 上)指出了 sokol_gfx.h 中的一个相关片段,其中 \'colors\' 被声明为另一种类型的数组,即结构体。(我认为)。我可能会稍后更新这个问题。

  • 引用 11

    未命名 struct 的有 3 名成员: pip , bind pass_action . sg_pipeline sg_bindings 可能是 typdef 'ed struct ,但我们无法确定,但我们知道是 sg_pass_action

    相应的变量 state pip 初始化 bind 为零,并且成员 pass_action 的成员 colors[0] 用复合值初始化:

    { .load_action = SG_LOADACTION_CLEAR, .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f } }

    的成员 pass_action colors 是一个数组, struct 其成员 load_action clear_value .

    clear_value 是一个至少有 4 个元素的数组,或者是 struct 具有至少 4 个成员的数组,可能是浮点类型。

    类似这样的内容(其中?是必需的信息,我们无法从提供的数据中得知):

    typedef struct {
        struct {
           ? load_action;
           float clear_value[4];
        } colors[?];
    } sg_pass_action;
    

    如果您还没有通过预处理器运行您的程序(例如 cpp )并检查输出。

  • 我在 WS-Federation 身份验证方面遇到问题。因此,我的设置如下:builder.Services.AddAuthentication(sharedOptions =>{ sharedOptions.DefaultScheme = CookieAuthenticationDefaults。

    我在 WS-Federation 身份验证方面遇到问题。因此,我的设置如下:

    builder.Services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
    })
    .AddWsFederation(options =>
    {
        options.Wtrealm = "https://dev-archive-console-admin.eisnot.ru/";
        options.MetadataAddress = "https://my-adfs.ru/FederationMetadata/2007-06/FederationMetadata.xml";
    })
    .AddCookie();
    
    builder.Services.AddAuthorization(options =>
    {
        options.AddPolicy("Publisher", policy =>
            policy.RequireClaim(ClaimTypes.Role, "dev_eis_archive_admin_publisher")
        );
    });
    
    [Authorize(Policy = "Publisher")]
    public class QueueController : Controller
    {
    

    因此,我看到了 adfs 登录页面,尝试登录后,我看到了错误 adfs 页面。我得到了日志,其中显示:错误:MSIS7042:同一客户端浏览器会话在过去 '1' 秒内发出了 '6' 个请求在此之后,我添加了响应和请求记录器,现在我看到了以下内容:

    因此,正如我所看到的 - 没有声明,但是我从 ADFS 的请求正文中获取了令牌,因此出现了重定向授权循环。有什么想法可以解决它吗?

  • 我们的团队在一个项目中工作,其中客户手动部署(复制/粘贴)我们为正在开发的 ASP.NET WEB FORMS Web 应用程序提供的更新版本(ascx,aspx,dll 等)。一些...

    我们的团队在一个项目中工作,其中客户为我们正在开发的 ASP.NET WEB FORMS Web 应用程序手动部署(复制/粘贴)我们提供的更新版本(ascx,aspx,dll 等)。

    有时客户会报告一些本应已经修复的问题,但我们不知道这是否可能是由于部署不当(复制文件错误等)造成的。

    我们无法访问生产或测试服务器,因此我们无法直接在客户的冗余(N)服务器上进行检查;这就是为什么我们需要一种替代方法。

    有没有一种“自动”的方法来检查它?让我解释一下我的猜测:

    • p5

    • p6

    欢迎任何想法,尽管我猜应该有更恰当的方法来做这件事,因为这应该是一个共同的要求。

    问候!

  • 嗯,这实际上并不常见,因为在大多数情况下,人们不会部署同一个网站的多个副本。

    此外,在大多数情况下,为了构建和部署,我们不会“手动”复制几页,而是使用发布向导。

    还有更糟糕的吗?大多数人不建议使用 asp.net 网站,但事实上,我们强烈建议您使用 asp.net web“应用程序”。

    使用 Web 应用程序时,不会将任何 aspx.cs(或 aspx.vb)页面部署到服务器。因此,网站在部署之前会进行预编译。这当然有很多好处,这里就不一一列举了。

    但是,使用应用程序的一个很大的缺点是您无法重新部署单个页面(以及后台代码),因为没有将后台代码页面部署到服务器。(只部署了 .dll 和 aspx 页面,所有源代码在发布时都被删除)。这意味着如果您更改给定页面的一行后台代码,则必须重新部署整个站点。如前所述,虽然这不是最理想的,但在几乎所有情况下,其众多优点都超过了必须进行完全重新部署的成本。

    因此,使用源代码(例如 GitHub)时,Web 应用程序的效果会好得多。因此,在大多数情况下,版本、分支和更改都由源代码控制进行管理(这只是使用源代码控制来维护网站“版本”的另一个巨大优势)。

    因此,不,鉴于上述情况,您的设置根本不常见,并且不是解决此问题的理想方法。因此,应向客户提供一个“Web 部署”包,Web 发布可以为您创建该包。这当然意味着,当您向此类客户提供该 Web 部署包时,他们会进行完全重新部署。(它由一个压缩文件夹和一个批处理文件组成,他们运行该批处理文件解压缩,复制到 Web 文件夹,然后它会为您重新启动 Web)。

    但是,您现在拥有的就是这些。我认为只需在每个页面上添加一个简单的隐藏字段控件即可。这样,每次更新这些页面时,开发人员都可以设置/添加/增加某个版本号。

    然后,在主母版页中,您可以有一个菜单选项,使用时会获取/抓取该隐藏字段,并显示该版本号。换句话说,假设所有页面都有该隐藏字段(具有相同的名称),那么母版页中的后台代码可以从隐藏字段中获取/抓取该版本号,并为每个给定页面生成一个结果。

    我根本不相信我会想要每个页面的版本号,因为这样客户随着时间的推移可能会与当前使用的主要源应用程序不同步。换句话说,虽然部署一个页面(.aspx 和 aspx.cs/aspx/vb 后面的相应代码)页面可能很棒,但这意味着现有代码将在一些页面中运行,这些页面对代码和从其他页面传递的 session() 值等做出了假设。

    因此,您具有松散的耦合,但是在很多情况下这太松散了!因此,这进一步减少了编译时引用(当然,这也是为什么我建议使用“应用程序” - 它们还具有更好的编译时依赖关系和代码解析能力)。

    因此,我认为在每个页面中都有一个隐藏字段控件是可行的,因为您需要显示该信息的能力,因此您可以在母版页中提供一个菜单选项,该选项可以根据用户正在查看的当前页面读取该隐藏值。

    一般情况下,我们不会将源代码部署到我们的网站,因此版本号是应用程序范围内的,而不是每个页面的。考虑到源代码控制的使用,开发人员社区中遇到与每个页面的版本号相关的此类问题的人就更少了。

返回
作者最近主题: