我应该使用异常来处理用户输入验证吗?

时间:2013-12-04 16:42:10

标签: c# asp.net-mvc asp.net-mvc-4

我正在将业务逻辑代码从我的控制器转移到业务类。我的页面需要大量的用户输入验证。这在我的代码中创建了许多嵌套级别。所以我在业务层重新编写了代码,如下所示:

    public RmaDetail SerialNumberScan(int rmaNumber, int serialNumber, RepairInvoice repairInvoice) {
    var result = SelectRmaDetail(rmaNumber, serialNumber);

    if (result != null) throw new BusinessException("Serial Number not found.");

    if (result.Received != 1) throw new BusinessException("Line item has not been received.");

    bool? workOrderClosed = WorkOrderClosed(result.LNSEQNBR, result.LNSEQNBR, serialNumber);

    if (!workOrderClosed.HasValue) throw new BusinessException("Work order not found.");

    if (workOrderClosed.Value == false) throw new BusinessException("Work order not closed.");

    repairInvoice.TerminalType = result.ITEMNMBR.Trim();
    repairInvoice.UnderWarranty = RepairInvoiceDataLayer.UnderWarranty(result.RETDOCID, result.LNSEQNBR, serialNumber, result.CUSTNMBR);

    return result;
}

这是我的控制器:

    public ActionResult SerialNumberScan(string rmaNumber, string serialNumber)
{
    if (ModelState.IsValid)
    {
        ModelState["SerialNumber"].Value = new ValueProviderResult(serialNumber, serialNumber, CultureInfo.CurrentCulture);
        try
        {
            var rmaDetail = BusinessLayer.SerialNumberScan(rmaNumber, serialNumber, repairInvoice);
            Session["RmaDetail"] = rmaDetail;
            ViewBag.SetFocusTo = "#RepairLevels";
        }
        catch (BusinessException ex)
        {
            ViewBag.AlertMessage = ex.Message;
        }
    }

    return View("Index", repairInvoice);
}

ViewBag.AlertMessage是显示在我页面顶部的消息。我喜欢这种方法,因为它非常易读。但是,我知道异常非常昂贵。有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

只有当您将它们作为正常程序流程的一部分抛出时,异常才会变得昂贵。一般情况下,应该使用异常来处理异常情况,因此您的用例肯定符合条件:缺少序列号或行项目的情况确实异常。

但是,我要改变的一件事是使用相同的异常(即BusinessException)来处理所有验证。一方面,这使得您的代码非常简单,因为您总是抛出相同的异常 - 唯一不同的是消息。另一方面,它会以不同的方式消除您处理每种情况的灵活性。

我认为向BusinessException引入sublcasses会带来更好的方法。添加新的异常 - 在这种情况下,MissingSerialNumberMissingLineItem异常,使它们成为BusinessException的子类,以便您可以根据需要一起处理它们,并在这些点使用无参数构造函数你抛出这些例外的地方。

答案 1 :(得分:2)

首先,例外情况只有在被抛出时才会很昂贵。如果出现问题,应该抛出它们。在性能方面,我不认为你应该在这种情况下担心它,我们不是在这里谈论,我们谈的是毫秒。用户肯定不会注意到抛出异常并告诉他们的费​​用。

同样偏离主题,您可以编写一个扩展方法,例如:

    public static void Throw<T>(this bool expression, string alert) where T : Exception
    {
        if (!expression)
            throw (T)Activator.CreateInstance(typeof(T), alert);
    }

然后你可以用:

替换所有if / throw检查
(result.Received != 1).Throw<BusinessException>("message");