c# - C# 处理 DAL 中的 WebExceptions
问题描述
有没有办法在数据访问层中正确处理 WebExceptions?
下面是SendReceive
我们的 DAL 中用于与远程服务器通信的方法,如果存在通信问题,例如无法访问端点,因此无法检索数据,我希望将用户重定向到视图,通知用户请稍后再试。
private static TResult SendReceive<TResult, TPayLoad>(string method, string route, TPayLoad payload, bool post, bool authentication, string hashedPassword)
{
var subject = "WebApplication1 - " + method + " Error";
using (var webClient = new WebClient())
{
try
{
var uri = new Uri("http://ourdomain/ourwebapicontroller/" + route);
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
if (authentication)
{
var hashedPasswordAsBytes = Encoding.UTF8.GetBytes(hashedPassword);
webClient.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Convert.ToBase64String(hashedPasswordAsBytes));
}
var response = post ? webClient.UploadString(uri, JsonConvert.SerializeObject(payload)) : webClient.DownloadString(uri);
var parsedResponse = JsonConvert.DeserializeObject<TResult>(response);
return parsedResponse;
}
catch (WebException webException)
{
SendEmail(subject, MvcApplication.To, MvcApplication.From, "<p>WebException [" + webException.Message + "]</p>");
// Issue with endpoint
}
catch (Exception exception)
{
SendEmail(subject, MvcApplication.To, MvcApplication.From, "<p>Exception [" + exception.Message + "]</p>");
}
}
return default(TResult);
}
public Models.WebApplication1.Test GetTest(int id)
{
return SendReceive<Models.WebApplication1.Test, int?>("GetTest", "get-test/" + id, null, false, false, null);
}
public int SetTest(Models.WebApplication1.Test test)
{
return SendReceive<int, Models.WebApplication1.Test>("SetTest", "set-test", test, true, false, null);
}
由于 DAL 是从 Controller 引用的,我不相信它可以使用throw new HttpException()
,但是可以这样处理:
public ViewResult Test(int id)
{
var test = Dal.GetTest(id);
if (test == null)
{
throw new HttpException(404, "Please try again later.");
}
return View(test);
}
宁愿在内部处理通信问题SendReceive
,而不是在控制器级别处理每个方法引用SendReceive
。
解决方案
一切都取决于您所说的“处理”甚至“异常”是什么意思。
控制器
在控制器中,如果客户端请求不存在的东西,你想做什么?404 是一个很好的响应。但是如果 DAL 抛出异常怎么办?将完全相同的结果返回给客户端是否有意义?告诉客户出了问题的 500 错误可能更有意义。
此处指出了这种不匹配:
throw new HttpException(404, "Please try again later.");
如果请求抛出异常(出于任何原因,包括 DAL),则返回 500 错误并带有“稍后再试”是有意义的。您正在清楚地传达问题出在您身上。对不起,希望它不会再发生,如果我们正在努力。
如果客户请求了一些不存在的东西,那么这可能会也可能不会改变。他们应该稍后再试吗?为什么?也许他们所要求的永远不会被发现。这也不例外。有人要求一些不存在的东西却一无所获,这意味着您的应用程序正在正常工作。404 告诉他们我们的应用程序正在运行——我们只是没有他们想要的东西。
基于此,将实际异常冒泡到控制器可能是有意义的。DAL 不知道控制器甚至网站。不知道调用者是否应该知道存在异常。
DAL “处理”异常可能意味着不同的事情。(我会省略我对哪个是正确的看法,因为它不相关。)
如果你的 DAL 抛出异常,你可以做一些事情。有些可能比其他更好,但同样,这取决于意见和需求。- 没做什么。让异常冒泡。- 记录并重新抛出它。- 记录它,然后将它包装在另一个提供一些上下文的异常中,并抛出新的异常。(是否包装异常是一个完整的讨论。)
有人会说“处理”异常是不同的东西,它涉及以某种方式对异常做出反应以解决问题,这是我们不太可能做的事情。例如,如果我们的应用程序从 API 检索每日 Chuck Norris 笑话但抛出异常,我们可能会记录它以便我们知道出了什么问题,然后用备份 Chuck Norris 笑话替换它。
我不会做的最重要的事情是“隐藏”异常,以便对调用者来说,异常和“未找到”看起来相同。如果出现问题,控制器需要知道——即使它不了解细节——所以它(不是 DAL)——可以确定应该与调用者通信的内容。
控制器与 DAL 之间的关系类似于浏览器客户端与控制器之间的关系。如果它不只是工作,我们会沟通。如果没有数据,我们会进行沟通。
我不建议将编写代码放在发送电子邮件的 DAL 中。这是非常具体的,它将您的所有代码与该决定以及可能与发送邮件的实现相结合。
另一种方法是定义这样的接口:
public interface ILog
{
void LogException(Exception ex);
void LogMessage(string message);
}
...并注入 DAL 类。发生异常时,调用_log.LogException(ex);
. 您的 DAL 不知道实现是什么。如果您愿意,您可以记录它甚至发送电子邮件。
推荐阅读
- node.js - 我不知道如何修复我的错误——node.js 和 npm
- machine-learning - ValueError: Error when checking target: expected block5_pool to have 4 dimensions, but got array with shape (60000, 10)
- java - 如何在java中打印二维数组?
- python - 如何通过 python-docx 使列表项目符号中的某些单词变为粗体
- .net - Outlook 插件 - Visual Basic Windows 窗体应用程序 - WebBrowser 控件内容不再显示
- jinja2 - jinja2 - 按顺序从 yml 读取项目变量
- memory-management - 通过内存映射(mmap 函数)访问 UART2 时出现“总线错误”
- google-search - robots.txt 中不允许的页面,但已被 Google 编入索引。怎么可能?
- java - 运算符'=='不能应用于'java.lang.String','int错误
- html - 我的网页正在使用烧瓶服务器加载图像