public JsonResult JoinMailingList(string txtEmail) { // ... return new JsonResult() { Data = new { foo = "123",success = true } }; }
然而(至少根据我的第一印象),这真的不是一个很好的分离关注点。
>单元测试方法更难写,因为他们没有很好的强类型数据进行测试,并且必须知道如何解释Json。
>对于未来通过HTTP(或任何涉及序列化的任何远程协议)的其他View来说,更难以插入,因为在这种情况下不必要的是序列化和反序列化响应。
>如果你有两个不同的地方需要这个动作的结果怎么办?一个人想要Json,另一个想要XML或者也可能是一个完整的or partially渲染视图。
我想知道为什么一个对象和Json之间的转换没有通过属性声明性地实现。在下面的代码中,您基本上告诉MVC,该方法可以转换为Json,然后如果从AJAX客户机调用该方法,则会检查内部执行的新JsonResult()转换的属性。
单元测试可以采取动作结果(ObjectActionResult)并拉出强类型的Foo。
[JsonConvertible] public ActionResult JoinMailingList(string txtEmail) { // ... return new ObjectActionResult() { Data = new Foo(123,true) }; }
我只是好奇的人们的想法和任何替代模式跟随。
这些也只是我的初步观察 – 可能还有更多的理由为什么这不是一个理想的设计(可能很多为什么它是一个完全可以接受和实际的设计!)我今天感觉理论和恶魔倡导。
*免责声明:我甚至还没有开始考虑如何实施这个属性,或者它可能产生什么副作用或后果等等。
解决方法
我曾经被告知:“让你的代码通用,不要让你的应用程序泛型。”
您正在编写应用程序控制器。应用程序控制器(其责任是减轻模型和视图之间的调用并调用模型的更改)可以了解某个视图(JSON,HTML,PList,XML,YAML)。
在我自己的项目中,我通常有以下的东西:
interface IFormatter { ActionResult Format(object o); } class HtmlFormatter : IFormatter { // ... } class JsonFormatter : IFormatter { // ... } class PlistFormatter : IFormatter { // ... } class XmlFormatter : IFormatter { // ... }
基本上是“格式化”,它们采取对象并给予不同的表示。如果HtmlFormatter的对象实现了IEnumerable,那么HtmlFormatters甚至足以输出表。
现在返回数据的控制器(或可以使用HtmlFormatters生成网站的部分)采用“格式”参数:
public ActionResult JoinMailingList(string txtEmail,string format) { // ... return Formatter.For(format).Format( new { foo = "123",success = true } ); }
您可以添加您的“对象”格式化程序进行单元测试:
class ObjectFormatter : IFormatter { ActionResult Format(object o) { return new ObjectActionResult() { Data = o }; } }
使用这种方法,您的任何查询/ actions / procedure / ajax调用,无论您想要调用它们,都可以以各种格式输出。