ASP.Net MVC 3 中处理 Ajax 调用的正确方法
当在 ASP.Net MVC 中编码 Ajax 调用时,我们有很多选择来发出调用、在服务器上处理它们以及在客户端上处理成功和失败。有些事情显然有正确的答案,但我一直无法找到明确的指导。那么,端到端的ajax调用的正确方法是什么?
包括
- 将url的action的url注入ajax调用的最佳方式是什么?
- 选择JsonBehavior时有哪些考虑因素?
- 在服务器端处理错误的最佳方法是什么?
- 客户端 error() 回调应该由任何错误(即意外的 OutOfMemoryException)触发,还是仅由可预见的错误(即无效输入)触发?
- 以触发 error() 回调的方式导出错误的最佳方式是什么。
- 确保错误回调获取正确状态代码和响应文本的最佳方法。
- 验证错误是否会导致错误状态代码,或者它们是否应该成为响应验证对象的一部分。
- 在客户端处理错误的最佳方法是什么?
- 服务器端意外错误是否应该以与验证摘要类似的方式显示?也许只是一个“出了问题”的对话框?客户应该能够区分两者吗?
人们对其他事情有强烈的看法吗?
When coding up Ajax calls in ASP.Net MVC we have a lot of options as far as issuing calls, handling them on the server, and dealing with successes and failures on the client. Some things clearly have a correct answer, but I've been unable to find clear-cut guidance. So, end-to-end, what is the correct way to make an ajax call?
Including
- What is the best way to inject the url of the action for the url into the ajax call?
- What are the considerations when choosing JsonBehavior?
- What is the best way to handle errors on the server side?
- Should the client side error() callback be triggered by any errors (ie unexpected OutOfMemoryException), or only by foreseeable errors (ie invalid input)?
- What is the best way of exporting errors in a way that the error() callback will be triggered.
- Best way of ensuring the error callback gets the correct status code and response text.
- Should validation errors result in an Error StatusCode or should they be part of a responding validation object.
- What is the best way to handle errors on the client side?
- Should unexpected errors server-side be displayed in a similar way as the validation summary? Maybe a just 'something-went-wrong' dialog? Should the client be able to distinguish between the two?
Any other things people have strong opinions on?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题/回答风格
将 URL 操作的 URL 注入 Ajax 调用的最佳方式是什么?
这方面没有惯例,而且很大程度上取决于您的内容如何呈现给客户。是通过视图/部分视图(在这种情况下,您可以使用
Html
/Url
辅助方法生成 URL,还是纯粹在客户端生成(模板等)。它是很常见的是,我们只希望使用 Ajax 行为扩展一些常见的 HTML 元素(例如表单、按钮和链接),在这种情况下,最好提供正确的 URL,我们也可以从中读取这些 URL 并在脚本中使用它们(例如href 链接)。对于用户来说,我们是否将它们转换为 GET/POST/DELETE/PUT 请求并不重要。在脚本中对 URL 进行编码,因为您可能会更改路由或提供其他处理方式,在维护方面,尽可能使用
Html
帮助程序是更好的方法。它们会自动(没有href
或src
属性),您始终可以将它们添加为自定义属性,特别是当您使用数据属性(例如data-href
或相似的)。阅读John Resig 的博客文章了解这些内容。选择JsonBehavior有哪些考虑因素?
当必须返回Json时最好发出POST请求。在 GET 请求中,您必须了解可能的影响 JSON 劫持< /a> 这也是您必须明确指定允许带有 JSON 结果的 get 请求的原因。
在服务器端处理错误的最佳方法是什么?
处理服务器错误(不能也不应该被抑制)的最佳方法是实际通知用户错误。它的细节通常并不重要,因为用户不熟悉开发,但告诉他们出了问题是可以的。特别是如果你可以为他们提供某种解决方案。通过 Ajax 调用,可以将错误返回为可以使用错误处理程序 Javascript 函数处理的错误。我写了一篇博客文章,详细介绍了整个过程提供显示如何正确处理验证错误的代码。我个人认为将错误返回为成功是错误的。因此我不这样做。但这是有争议的。我使用的代码相当简化了我的控制器操作:
客户端 error() 回调应该由任何错误(即意外的 OutOfMemoryException )触发,还是仅由可预见的错误(即无效输入)触发)?
如前所述,当用户从其发起的操作中获得意外结果时,应向用户报告错误。不要隐瞒应该向他们报告的错误。但不要讨论太多细节。内存不足异常对于普通计算机用户来说有点太复杂了。报告一些人性化且简短的内容。
以触发
error()
回调的方式导出错误的最佳方式是什么。查看我的博客文章并检查代码以了解如何创建由
error()
函数处理的错误确保错误回调获取正确状态代码和响应文本的最佳方法。
相同博客文章
验证错误是否会导致错误< code>StatusCode 或者它们应该是响应验证对象的一部分。
验证错误实际上本质上是警告,应该这样对待。这就是为什么您可以在某些网站上看到肯定的表单验证模式,这些网站还会报告数据何时有效,而不仅仅是通知用户他们又犯了另一个错误。验证错误通常源于无效的用户界面体验和信息不足。
在客户端处理错误的最佳方法是什么?
这很大程度上取决于您的应用程序,但我建议您遵循经过验证的模式,因为用户可能知道该怎么做并且不会混淆。您认为为什么 OpenOffice 使用与 Microsoft Office 几乎相同的 UI?因为用户知道它是如何工作的,所以更有可能快速、轻松地熟悉该应用程序。但如果可以的话,不要把用户当作傻子。使用积极的验证。有些错误也应该显示为错误。哦。顺便提一句。我在我的应用程序中使用不引人注目的信息,其中向用户报告成功操作等信息,但不会干扰他们的工作。一段时间后它会自动消失。与 GMail 的做法类似。它只是通知您邮件已发送,并且此信息不需要任何确认。
jQuery
ajax()
函数支持成功和错误函数,因此使用这两个函数是明智的。再次强调:将错误视为成功是不对的。我们根本不需要误差函数。我的 HandleModelState 操作过滤器返回带有可以使用的特定 400 错误代码的错误及其结果。服务器端意外错误是否应该以与验证摘要类似的方式显示?也许只是一个“出了问题”对话框?客户应该能够区分两者吗?
人们不喜欢大红色警报。如果某些内容本质上是警告,则应该比阻止应用程序正常运行的实际错误更友好地对待它。验证尤其应该非常友好。错误应该由用户确认,警告可能不应该。取决于他们的性质。但如果它们应该是,那么它们可能是错误的。
我希望这能为您清除一些事情。
Question/Answer style
What is the best way to inject the URL of the action for the URL into the Ajax call?
There's no convention about this and it also largely depends how your content has been brought to the client. Was it via views/partial views (in which case you could generate URLs with
Html
/Url
helper methods or is it purely generated on the client (templating and such). It's quite common that we just want some usual HTML elements to extend with Ajax behaviour (like forms, buttons and links). In this situation it's best to provide correct URLs that we can also read from them and use them in our scripts (likehref
in links). It's also more clear to users where things are pointing to. Whether we convert them to GET/POST/DELETE/PUT requests doesn't really matter any more. I would suggest to avoid hard-coding URLs in your scripts because you may change routing or provide other means of processing. By usingHtml
helpers wherever possible is a much better way in terms of maintenance. When adding URLs to elements that don't support them automatically (nohref
orsrc
attribute) you can always add them as custom attributes especially when you use data attribute (likedata-href
or similar). Read John Resig's blog post about these.What are the considerations when choosing JsonBehavior?
It's best to make POST requests when you have to return Json. In GET requests you have to be aware of the possible implications JSON Hijacking that's also the reason why you have to explicitly specify that you allow get requests with JSON results.
What is the best way to handle errors on the server side?
The best way to process server errors (that can't and shouldn't be suppressed) is to actually inform the user of the error. Details of it are usually not important since users are not development savvy but telling them something went wrong is ok. Especially if you can offer them some sort of a solution. And with Ajax call it's bets to return errors as errors that can be handled with error handler Javascript functions. I've written a blog post that details the whole process and also provides the code that shows how to correctly handle validation errors. I personally think that returning errors as success is wrong. hence I don't. But that's argumentative. My controller actions are rather simplified by the code I use:
Should the client side error() callback be triggered by any errors (ie unexpected
OutOfMemoryException
), or only by foreseeable errors (ie invalid input)?As stated previously errors should be reported to users when they will get unexpected results from what they initiated. Don't suppress errors that should be reported to them. But don't go into too much detail. Out of memory exception is a bit too complex to explain tu usual computer users. Report something human friendly and short.
What is the best way of exporting errors in a way that the
error()
callback will be triggered.Look at my blog post and check the code to see how to create errors that are handled by the
error()
functionBest way of ensuring the error callback gets the correct status code and response text.
Same blog post
Should validation errors result in an error
StatusCode
or should they be part of a responding validation object.Validation errors are actually warnings by nature and should be treated as such. That's why you can see positive form validation pattern on some sites that also report when data is valid instead of just informing users that they've made yet another mistake. Validation errors are usually rooted in invalid user interface experience and insufficient information.
What is the best way to handle errors on the client side?
This largely depends on your application but I suggest you follow proven patterns because users are likely to know the drill and won't confuse them. Why do you think OpenOffice uses almost identical UI as Microsoft Office? Because users know how it works so it's more likely to be acquainted with the app fast and painlessly. But if you can, don't treat users as dumb people. Use positive validation. Some errors should also be displayed as errors. Oh. Btw. I use unobtrusive infos in my app where information such as successful operation is reported to users but doesn't intrude their work. It automatically disappears after a while. Similar to what GMail does. It just informs you that mail has been sent and this info doesn't need any confirmation.
jQuery
ajax()
functin supports success and error functions, so it's wise to use both. Again: Returning errors as success is not right. We wouldn't need error functions than at all. My HandleModelState action filter returns errors with particular 400 error code that can be used and its result as well.Should unexpected errors server-side be displayed in a similar way as the validation summary? Maybe a just "something-went-wrong" dialog? Should the client be able to distinguish between the two?
People don't like the big red alerts. If something is a warning by nature it should be treated friendlier than actual errors that prevent your app to work properly. Validation in particular should be very friendly. Errors should be confirmed by users, warnings maybe shouldn't. Depends on their nature. But if they should be then they're probably errors.
I hope this clears some things for you.
就我个人而言,我在 AJAXify 的 DOM 元素上使用 HTML5 data-* 属性。例如:
然后:
当然,如果 DOM 元素表示锚点或表单,我将使用本机属性(action 或 href)。
没有具体的考虑。请记住,GET 请求可能会被客户端浏览器缓存,因此您可能需要在客户端上指定
{cache: false }
。哦,当然还有服务器上的 Json 的AllowGet。我个人使用 FluentValidation.NET 来处理视图模型上的验证错误。也可能存在来自服务层。
如果服务器返回 JSON,我通常有一个如下所示的结构:
或:
取决于是否有错误,并且在客户端:
我对客户端上未处理的异常的所有内容使用
error
回调服务器在这种情况下只显示一些通用错误消息。可以使用 $.ajaxSetup 指定全局错误处理程序。为了简化服务器上这些 JSON 结果的生成并干燥我的操作,我使用自定义操作过滤器来测试该请求是否是 AJAX 请求,如果是 AJAX 请求,则测试是否有验证错误添加到 ModelState 中以及它们是否存在我们将操作结果替换为自定义错误 JsonResult 以处理错误情况。
Personally I use HTML5 data-* attributes on DOM elements which I AJAXify. For example:
and then:
Of course if the DOM element represents an anchor or a form I would use the native property (action or href).
No specific considerations. Bear in mind that GET request might be cached by client browsers so you might need to specify
{ cache: false }
on the client. Oh and of course AllowGet on the server for Json.Personally I use FluentValidation.NET to handle validation errors on my view models. There could also be errors coming from the service layer.
If the server returns JSON I usually have a structure which looks the following:
or:
depending on whether there was an error, and on the client:
I use the
error
callback for everything that is unhandled exceptions on the server in which case simply show some generic error message. A global error handler could be specified using$.ajaxSetup
.To ease the generation of these JSON results on the server and DRY my actions I use custom action filters which would test whether the request was an AJAX request and if it was an AJAX request test whether there were validation errors added to the ModelState and if they were replace the action result with a custom error JsonResult in order to handle the error case.
以下是我在最近的一些项目中所做的事情:
1)我使用 Url.Action 调用将 ajax url 注入视图中。
2) Jqgrid 使用 GET 来获取网格数据,因此在填充网格控制器操作中,我需要在 Json 方法调用中使用 JsonRequestBehavior.AllowGet 开关。
3)我最近切换到微软的不显眼的客户端验证,它有一个简洁的 ModelState.IsValid 方法,您可以在控制器操作中运行服务器端,以确保同样的验证也在服务器端运行,而无需重复代码。需要一些工作来将其与 jquery.maskedinput 等相结合以屏蔽/取消屏蔽数据,这里有一篇关于如何让所有这些发挥作用的文章。
4)关于显示错误客户端,这是一个设计问题,必须由利益相关者充实。就我个人而言,我不喜欢文本框旁边的验证或页面顶部的验证摘要。我更喜欢错误在你面前跳出来,所以我调整了 Microsoft 的 jquery.validate.unobtrusive.js 以在弹出模式对话框中显示错误。您可以在 jquery.validate.unobtrusive.MOD.js 文件中看到上述解决方案中的代码(注意我的版本带有“.mod.js”后缀),并且您可以在 Site.Master 中看到错误对话框。
控制器操作示例:
希望这有帮助,
罗伯特
Here's how I do things in some recent projects:
1) I inject the ajax url in the view with a Url.Action call.
2) Jqgrid uses GETs to fetch grid data, so in the fill grid controller actions I need to use the JsonRequestBehavior.AllowGet switch in the Json method call.
3) I recently switched to Microsoft's unobtrusive client-side validation, which has a neat ModelState.IsValid method you can run server-side in your controller action to make sure the same exact validation is also running on the server side without code duplication. It took some work meshing it with jquery.maskedinput and so on to mask/unmask data, here's the article on how to get all that to work.
4) Regarding displaying the error client side, that's a design issue that has to be fleshed out by the stakeholders. Personally, I didn't like the validation next to the textboxes or a validation summary at the top of the page. I prefer the errors to jump out at your face, so I tweaked Microsoft's jquery.validate.unobtrusive.js to show the error in a popup modal dialog. You can see the code in the solution above in the jquery.validate.unobtrusive.MOD.js file (notice that my version is suffixed with ".mod.js") and you can see the error dialog in the Site.Master.
Example of controller action:
Hope this helps,
Robert