Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.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# 如何消除控制器方法中重复的空检查和异常处理?_C#_Design Patterns_.net Core_Asp.net Core Webapi - Fatal编程技术网

C# 如何消除控制器方法中重复的空检查和异常处理?

C# 如何消除控制器方法中重复的空检查和异常处理?,c#,design-patterns,.net-core,asp.net-core-webapi,C#,Design Patterns,.net Core,Asp.net Core Webapi,我希望避免使用重复的try/catch块、重复的日志记录命令,并考虑HTTP响应代码,如404、200、204等,并将API方法代码行最小化到某些接口或服务中。换句话说,让我的代码更加枯燥 鉴于此代码: [HttpGet()] [Route("Contracts/{id}")] public async Task<IActionResult> Get(int id) { try { var re

我希望避免使用重复的try/catch块、重复的日志记录命令,并考虑HTTP响应代码,如404、200、204等,并将API方法代码行最小化到某些接口或服务中。换句话说,让我的代码更加枯燥

鉴于此代码:

    [HttpGet()]
    [Route("Contracts/{id}")]
    public async Task<IActionResult> Get(int id)
    {
        try
        { 
            var results = await _service.GetContractByIdAsync(id);
            if (results == null) { return NotFound(); }             
            return Ok(results);
        }
        catch(Exception ex)
        {
            _log(ex);
            return StatusCode(500); 
        }
    }

将会重复。我如何避免这种重复?也许我以后会想改变我处理错误的方式,而且我不想在很多地方改变它。

您可以定义一个
resultfilteratAttribute
,它将所有
ObjectResult
的空值更改为
NotFoundResult
。您可以在应用控制器方法的任何位置对其进行注释,甚至可以全局注册过滤器。另请参阅本文了解如何以及为什么

该属性如下所示(来自上述文章的代码)

将其应用于控制器方法并仅返回结果

[HttpGet()]
[Route("Contracts/{id}")]
[NotFoundResult]
public async Task<IActionResult> Get(int id) {
    var results = await _service.GetContractByIdAsync(id);
    return results;
}
[HttpGet()]
[路线(“合同/{id}”)]
[未找到结果]
公共异步任务Get(int-id){
var results=wait_service.GetContractByIdAsync(id);
返回结果;
}
确保控制器使用
ApiController
属性修饰。我省略了try-catch块,因为您也可以让管道处理异常。在
启动中。配置
方法为
app.UseExceptionHandler(…)
注册lambda


查看Microsoft ASP.NET核心文档-了解更多详细信息。

挑战1:尝试/捕获

您可以在MVC之前添加,它将在try/catch块中执行下一个中间件(包括MVC):

public void配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
//...
app.useMeyExceptionHandler();
// ...
app.UseMvc();
}
中间件可以如下所示:

公共类例外HandlerMiddleware
{
readonly RequestDelegate\u next;
只读ILogger记录器;
公共例外HandlerMiddleware(RequestDelegate下一步,ILogger记录器)
{
_下一个=下一个;
this.logger=记录器;
}
公共异步任务调用(HttpContext上下文)
{
尝试
{
等待下一步(上下文);
}
捕获(例外e)
{
等待HandleExceptionAsync(上下文,e);
}
}
私有任务HandleExceptionAsync(HttpContext上下文,异常)
{
//记录例外情况
字符串结果=…如果需要,请键入响应
context.Response.ContentType=“应用程序/json”;
context.Response.StatusCode=500;
返回context.Response.WriteAsync(结果);
}
}
我使用扩展方法将其添加到app builder中:

公共静态类MiddlewareExtensions
{
公共静态IAApplicationBuilder UseMeyExceptionHandler(此IAApplicationBuilder生成器)
{
返回builder.UseMiddleware();
}
}
现在您可以从所有控制器操作中删除
try/catch
,因为中间件将捕获所有未处理的异常

还有一些这样做可能会对你有所帮助

挑战2:未找到的空检查

您可以创建所有控制器将从中继承的一些基本控制器,并处理
null
检入:

公共类BaseController:ControllerBase
{
受保护的IActionResult CreateResponse(对象结果)
{
如果(结果==null)
返回NotFound();
返回Ok(结果);
}
}
然后使所有控制器从中继承:

[ApiController]
公共类YourController:BaseController
// ...
现在,您的操作方法可以如下所示:

[HttpGet()]
[路线(“合同/{id}”)]
公共异步任务Get(int-id)
{
var results=wait_service.GetContractByIdAsync(id);
返回CreateResponse(结果);
}

…问题是什么?您想要错误处理,但不想要try-catch块,您想要条件,但不想要if语句…?问题是如何实现经常重用的模式,而不是复制和粘贴一堆代码。条件语句(if/then)是代码复杂性和可能不必要的代码路径,接口或类也可以这样做。我没有说我不想尝试捕捉,我说我不想在API中复制粘贴很多次。谢谢,sry,我不太清楚。我理解这个问题。他想要试一试/接球和其他的,但不要重复。这里仍然没有问题。我们知道您想要什么,但您没有试图清理的代码,也没有提出任何问题。你到底在找什么?
public class NotFoundResultFilterAttribute : ResultFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        if (context.Result is ObjectResult objectResult && objectResult.Value == null)
        {
            context.Result = new NotFoundResult();
        }
    }
}
[HttpGet()]
[Route("Contracts/{id}")]
[NotFoundResult]
public async Task<IActionResult> Get(int id) {
    var results = await _service.GetContractByIdAsync(id);
    return results;
}