微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何处理控制器中的扩展方法?

如何解决如何处理控制器中的扩展方法?

我真的没有得到这个问题的正确标题。如有误导请更正。

我有一个 WebApi 控制器,其中有多个验证检查。控制器示例代码

      public async Task<IActionResult> UploadFile(IFormFile file)
        {
            try
            {
              return file.IsValid();

             //some more Functionality
             }
        }

这里的Isvalid是一个Extension方法代码如下

public static IActionResult PrepareResult(this ControllerBase controller,IFormFile file)
        {
            if (file== null)
            {
                return controller.Badrequest("No data sent");
            }
            return controller.Ok();
        }

问题:- 在当前场景中,如果文件为 Null,那么扩展方法将返回 Badrequest() 并且同样将返回给客户端。但是如果文件不为空,那么它将返回 Ok() 并且同样将返回给 Clint,因为我有更多的代码要执行(ie//一些更多的功能)。

我不想返回 controller.Ok(),以便在积极的情况下我可以继续使用剩余的代码

注意:- 我不想分配给任何变量并检查 If 条件。为了避免 if 条件只有我使用扩展方法

解决方法

不确定为什么您不想分配变量并避免 if 条件,因为这是最有效的方法。您可以使用异常处理,但这会带来性能成本。

public static void EnsureFileIsValid(this IFormFile file)
{
    if(file == null) { throw new InvalidOperationException("No data sent"); }
}
public async Task<IActionResult> UploadFile(IFormFile file)
{
    try
    {
        file.EnsureFileIsValid();
        return Ok();
    }
    catch(InvalidOperationException ex)
    {
        return BadRequest(ex.Message);
    }
}
,

您可以将操作传递给您的方法,例如:

public static IActionResult PrepareResult(this ControllerBase controller,IFormFile file,Action<IFormFile> work)
{
    if (file == null)
    {
        return controller.Badrequest("No data sent");
    }
    work(file);
    return controller.Ok();
}

在你的行动中,用途是:

public class FilesController : ControllerBase
{
    [HttpPost]
    public IActionResult UploadFile([FromServices]IFileService fileService,IFormFile file)
    {
        return Ok(PrepareResult(file,fileService.Upload));
    }
}

但也许你可以考虑使用验证。

在验证步骤中,您使用 RequiredAttribute 强制参数不为空。

ApiControllerAttribute 在调用操作之前强制执行验证。如果验证失败,则 ASP.NET Core 直接返回 BadRequest 并且不调用操作。

在本例中,如果参数文件为空,则不会调用该操作并返回 BadRequest :

[ApiController]
public class FilesController : ControllerBase
{
    [HttpPost]
    public IActionResult UploadFile([Required]IFormFile file)
    {
        //Do something
        return Ok();
    }

    [HttpPut]
    public IActionResult UploadFileBis([Required] IFormFile file)
    {
        //Do something
        return Ok();
    }
}

PS : 您可以在程序集级别使用 [ApiControllerAttribute],它将对程序集中的所有控制器启用:

[assembly: ApiController]
,

如果你想在同一个下层类中验证条件并定义错误响应,这里有一个解决方案。

首先,让我们创建一个自定义异常来保存要返回的 http 状态代码和消息:

// serialization implementation redacted
public class InfrastructureException : Exception
{
    public HttpStatusCode HttpStatusCode { get; }
    public InfrastructureException(HttpStatusCode code,string message) : base(message)
    {
        HttpStatusCode = code;
    }
}

我们需要一个类来处理响应序列化:

public class ExceptionResponse
{
    public int StatusCode { get; set; }
    public string Message { get; set; }
    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

然后创建一个处理异常的中间件:

public class InfrastructureExceptionMiddleware
{
    private readonly RequestDelegate next;
    public InfrastructureExceptionMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext,IHostEnvironment hostEnvironment)
    {
        try
        {
            await this.next(httpContext);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(httpContext,ex);
        }
    }

    private Task HandleExceptionAsync(HttpContext context,Exception exception)
    {
        context.Response.ContentType = "application/json";
        ExceptionResponse response = exception is InfrastructureException infrastructureException
            ? new ExceptionResponse()
            {
                StatusCode = (int)infrastructureException.HttpStatusCode,Message = infrastructureException.Message
            }
            : new ExceptionResponse()
            {
                StatusCode = (int)HttpStatusCode.InternalServerError,Message = ReasonPhrases.GetReasonPhrase(context.Response.StatusCode)
            };

        return context.Response.WriteAsync(response.ToString());
    }
}

现在,我们需要注册我们的中间件:

public class Startup
{
    public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
    {
        // redacted
        app.UseMiddleware<InfrastructureExceptionMiddleware>();
        // redacted
    }
}

在控制器中,我们将验证委托给扩展方法:

public async Task<IActionResult> UploadFile(IFormFile file)
{
    file.IsValid();
    // now you can consider file is valid
}

最后,在扩展方法中,我们抛出异常:

public static void IsValid(this IFormFile file)
{
    if(file == null)
    {
        throw new InfrastructureException(HttpStatusCode.BadRequest,"No data sent");
    }

    if(...) // condition for Http NotFound
    {
        throw new InfrastructureException(HttpStatusCode.NotFound,"Data not found");
    }

    // other validation conditions
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?