【问题标题】:custom exception for null parameters in c#c#中空参数的自定义异常
【发布时间】:2021-08-03 05:36:54
【问题描述】:

我正在尝试为 Web-API 程序创建自定义异常,如果名称、代码或任何内容为空,它应该向我发送一条自定义消息,说明 x 输入为空或空错误,我不确定如何完成它,所以我会很感激一些帮助。

public Product CreateProduct(Product p)
{    
    if (p.Name.Trim() == "")
    {
        throw new InvalidProductDataException("El producto no tiene nombre");
    }
    return p;                     
}

【问题讨论】:

  • 如果要检查字符串是否为null或空值,可以使用方法string.IsNullOrWhiteSpace来简化检查。查看更多信息:docs.microsoft.com/en-us/dotnet/api/…
  • 这通常会导致 400 Bad Request 和一条消息说明数据有什么问题,以便消费者可以尝试修复它。
  • 但是如果我不想使用 string.IsNull 异常并想创建我的名为 InvalidProductDataException 的异常,我该怎么做呢?
  • String.IsNullOrWhitespace(和String.IsNullOrEmpty)不是异常,它们只是返回真或假的静态函数。 Zokka 只是建议使用.Trim() 并检查与"" 是否相等并不是执行此检查的最优雅的方式。
  • 这能回答你的问题吗? How to write User Defined exceptions in C#?

标签: c# asp.net visual-studio


【解决方案1】:

我假设CreateProduct 是控制器类上的一个操作方法,而您实际上想要做的是将错误返回给调用您的 API 的客户端。因此,向 HTTP 客户端返回错误的最简单方法是使用 IActionResult 返回类型,而不是返回您的实际类型。这将使您能够控制 HTTP 状态代码。

class ProductController : Controller {

  public IActionResult CreateProduct(Product p)
  {
    if (String.IsNullOrWhitespace(p.Name))
    {
      return BadRequest("El producto no tiene nombre");
    }

    // Perform create?
    return Ok(p);   
  }
}

有关控制器操作返回类型的更多信息,请参阅:https://docs.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-5.0

从控制器操作引发的任何类型的异常都会导致向 API 客户端发送不透明的 HTTP 500 响应,这可能不是您想要的此类错误。

另一种方法是引入Middleware,它将捕获某些类型的异常并将它们转换为 HTTP 响应。

【讨论】:

  • 我试图不使用 String.IsNullOrWhitespace(p.Name) 但使用 InvalidProductDataException 创建一个异常
  • 老实说@PaolaVilaseca,我认为您并不真正了解您要做什么。但是,如果您真的想定义并抛出自定义异常类型,我已经发布了有关如何执行此操作的替代答案。不过我也将此问题标记为与stackoverflow.com/questions/3852751/… 重复
【解决方案2】:

让我们定义一个名为 LoginException 的自定义异常,用于在登录过程中抛出错误异常。

public class LoginException : System.Exception
    {
       //todo
    }

现在让我们定义在应用程序中使用的必要构造函数。

public class LoginException : System.Exception
 {
     public LoginException()
         : base()
     { }
 
     public LoginException(String message)
         : base(message)
 
     { }
 
     public LoginException(String message, Exception innerException)
         : base(message, innerException)
     { }
 
     protected LoginException(SerializationInfo info, StreamingContext context)
         : base(info, context)
     { }
 }

如上所示,我们已经定义了 LoginException 的构造函数,并为 System.Exception 类做了构造函数重定向,所以我们准备好 LoginException 类了。

void Login(string userName, string password)
       {
           try
           {
               if (userName != "canert" && password != "qwerty123")
                   throw new LoginException("Invalid login operation");
           }
           catch (LoginException loginException)
           {
               Response.Write(loginException.Message);
           }
       }

【讨论】:

    【解决方案3】:

    如果您想抛出一个名为InvalidProductDataException 的自定义异常类型,那么您需要声明一个具有该名称的类,并且它必须是System.Exception 的子类:

    public class InvalidProductDataException : System.Exception {
        public InvalidProductDataException(String message) : base(message) {
        }
    
        // This constructor overload is necessary to allow for your Exception to be deserialized. This is a best practice when implementing custom Exception types.
        protected InvalidProductDataException(SerializationInfo info, StreamingContext context) :
          base(info, context) {
    
          // If you exception contained custom properties, you would want to deserialize them here
        }
    }
    

    有关创建自定义异常类的更多信息,请参阅:https://docs.microsoft.com/en-us/dotnet/standard/exceptions/how-to-create-user-defined-exceptions

    注意:创建自定义异常类并不是为了能够指定您想要的消息。例如,您可以简单地throw new Exception("your message")。但是,如果您希望能够在代码的其他地方捕获特定异常,那么创建自定义异常类确实很有意义。

    【讨论】:

      猜你喜欢
      • 2021-04-20
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-24
      • 2012-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多