在同一个Action方法中包含单独的try / catch块是不好的做法

时间:2013-07-31 20:47:24

标签: asp.net-mvc entity-framework

我有以下删除操作方法,主要执行两个单独的任务: -

  1. 使用API​​调用从第三方应用程序中删除记录。
  2. 使用实体框架从我们自己的系统上的数据库中删除记录。
  3. 我的行动方法如下: -

    [HttpPost, ActionName("Delete")]
    public ActionResult DeleteConfirmed(int id)
    {
        var message = "";
        var status = "";
        var tag = "";
        Resource resource = new Resource();
        try
        {
            Rack rack = repository.FindRack(id);
            tag = rack.Technology.Tag;
             resource = repository.GetResource(rack.Technology.IT360ID.Value);
        }
        catch (NullReferenceException)
        {
            return Json(new
            {
                IsSuccess = "False"
            }, JsonRequestBehavior.AllowGet);
        }
        catch (DbUpdateException)
        {
            return Json(new
            {
                IsSuccess = "AlreadyUsed"
            }, JsonRequestBehavior.AllowGet);
        }
    
        using(var client = new WebClient())
        {
            var query = HttpUtility.ParseQueryString(string.Empty);
             query["username"] = "testuser";
            query["assetType"] = resource.ComponentDefinition.ComponentType.COMPONENTTYPENAME;
            query["operation"] = "DeleteAsset";
            query["assetName"] = resource.RESOURCENAME;
            var url = new UriBuilder("http://win-spdev:8400/servlets/AssetServlet");
            url.Query = query.ToString();
            try
            {
                string xml = client.DownloadString(url.ToString());
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);
                status = doc.SelectSingleNode("/operation/operationstatus").InnerText;
                message = doc.SelectSingleNode("/operation/message").InnerText;
            }
            catch (WebException ex)
            {}
        }
    
        if (status.ToUpper() == "SUCCESS")
        {
            try
            {
                repository.DeleteRack(id, User.Identity.Name);
                repository.Save();
                 return Json(new
                {
                    IsSuccess = "True", id = id, description = tag
                }, JsonRequestBehavior.AllowGet);
            }
            catch (NullReferenceException)
            {
                return Json(new
                {
                    IsSuccess = "False"
                }, JsonRequestBehavior.AllowGet);
            }
            catch (DbUpdateException)
            {
                return Json(new
                {
                    IsSuccess = "AlreadyUsed"
                }, JsonRequestBehavior.AllowGet);
            }
        }
         return RedirectToAction("Delete", new
        {
            id = id
        });
    }
    

    由于我使用实体框架来执行删除以及API调用,所以我最终得到了单独的try / catch块。那么我的动作方法逻辑会考虑一个糟糕的设计,因为我在同一个动作方法中有多个try / catch块吗?还有什么更好的方法可以遵循?

3 个答案:

答案 0 :(得分:2)

单独的错误案例肯定不是坏事。

但是,不良做法是捕捉非特定错误。您将为所有 DbUpdateException返回“已使用”。可能还有其他原因,而不是您计划的原因。如果发生这种情况,你就会吞下错误并产生一个无声的bug。你现在可能缺乏想象力,这些情况可能是什么,但这只是因为你永远不会在错误发生之前就知道错误。我建议你通过解释异常对象(可能解释消息,上帝禁止)或者通过收紧捕获的区域来准确地说明可以给出错误的语句来捕获更具体的信息。

简而言之,不要吞下表示错误的异常。错误总是发生,你想了解它们并修复它们。

另外,出于同样的原因,永远不要抓住NullReferenceException。它们总是违反常规。插入if已处理null

答案 1 :(得分:1)

将try-catch范围限制在尽可能少的范围内没有任何问题 (我可能会因此受到抨击。)

答案 2 :(得分:1)

如果try-catch中的代码是“逻辑实体”,例如做一个不会影响剩余代码的独立功能,或者如果它有错误,它不会导致错误的逻辑(错误执行)到下面的代码。然后为什么不呢。

但如果它会破坏你的程序逻辑,那么它应该被停止并且应该处理错误(try-catch块的范围。这一切都取决于你的程序逻辑。