ASP.NET MVC:让 AP​​I 控制器操作返回 View 和/或 JSON 是不是是一种好习惯

Posted

技术标签:

【中文标题】ASP.NET MVC:让 AP​​I 控制器操作返回 View 和/或 JSON 是不是是一种好习惯【英文标题】:ASP.NET MVC: Would it be good practice to have an API Controller action return both View and/or JSONASP.NET MVC:让 AP​​I 控制器操作返回 View 和/或 JSON 是否是一种好习惯 【发布时间】:2011-01-03 22:20:58 【问题描述】:

我正在编写一个可供 Web 应用程序和移动应用程序使用的 API,并且我在我的技术堆栈中使用 ASP.NET MVC 2。

目前,我有一个类似 Rest 的 API 服务,它以 JSON 格式返回数据。 这适用于移动应用程序,但我也想让它也适用于网络应用程序。

让控制器操作返回 html 视图或 JsonResult 是否是解决此问题的好方法?

Web 应用和移动应用的唯一区别是视图层;应用逻辑是一样的。

我想我可以创建一个用于 Web 应用程序的控制器,但我认为很多逻辑会从 API 控制器中复制。

编辑

我确实有另一个层来处理所有应用程序逻辑,但是 API 控制器仍然有一些逻辑来验证参数和在返回 JSON 响应时进行错误处理。到目前为止,重复的逻辑将是验证部分。

这里是一些代码sn-ps:

public JsonResult GetList(string accessToken, string listId)
 
    if (string.IsNullOrEmpty(accessToken))
        return Json(new  success = false, exceptionMessage = "Facebook access token is required." );
    if (string.IsNullOrEmpty(listId))
        return Json(new  success = false, exceptionMessage = "The list id is required." );

    string facebookId = null;
    var facebookIdParseSuccess = GetFacebookId(accessToken, out facebookId);

    if (!facebookIdParseSuccess)
        return Json(new  success = false, exceptionMessage = "There was a problem accessing your Facebook profile information." );

    try
    
        _groceryListManager.FacebookId = facebookId;
        var groceryList = _groceryListManager.GetList(listId);
        GroceryListViewModel mappedList = new GroceryListViewModel();
        Mapper.Map(groceryList, mappedList);
        return Json(new  success = true, results = mappedList );

    
    catch (Exception ex)
    
        return Json(new  success = false, exceptionMessage = "...");
    

【问题讨论】:

【参考方案1】:

如果您的视图模型也适合以 JSON 格式返回,那么在同一个操作中执行这两种操作会很好。比如:

public ActionResult Foo()

  FooModel model = new FooModel();

  // Code here to build the model

  if (Request.IsAjaxRequest())
    return Json(model);
  else
    return View(model);

这也有助于引导您在使用渐进增强方面取得成功。如果 HTML 和 JSON 的 URL 相同,那么在您的标记中使用可访问/SEO 友好的 URL 会容易得多,然后通过添加不显眼的事件处理程序以在支持 javascript 的浏览器中将其替换为对 JSON 的请求来逐步增强。

【讨论】:

这听起来是个好方法! IsAjaxRequest 的值是否由 post 变量之一确定? 它是通过测试设置X-Requested-With HTTP 标头与值XMLHttpRequest 的半标准约定来确定的,某些AJAX 库会在其异步请求上自动设置。这些库包括 MicrosoftAjax.js 和 jQuery,因此涵盖了我们大多数使用 ASP.NET MVC 的人。如果您使用其他东西或手动滚动您的请求,您仍然可以手动设置该 HTTP 标头,它会被 Request.IsAjaxRequest() 正确反映。 我必须为此做足功课,但是当移动应用程序调用 API 时,Request.IsAjaxRequest() 也必须为真。无论哪种方式,我确信我对它进行了编程,以便移动应用程序确实将 X-Requested-With 设置为 XMLHttpRequest。【参考方案2】:

我以前见过一个操作方法同时返回,但是,在我看来,最好有两个单独的操作方法。您可以让它们都使用共享代码调用另一个方法,但由于它们用于两个非常不同的事情,您可能会发现如果您有两个方法更容易维护(未来的需求可能会导致一个在这种方式使得很难在单一方法中同时支持两者)。

它们是否在同一个控制器中实际上更多地取决于应用程序的性质、大小和复杂性。我已将 API 作为与 HTML 完全不同的项目分开。我已经共享了用于访问数据和其他常用功能的 dll,但 MVC 项目不同。

【讨论】:

谢谢!在查看 API 调用列表后,只有少数需要 Html 视图,我认为为应用程序的网站部分设置一个单独的控制器会更简单。我仍然可以通过 AJAX 调用 API 操作,并且 API 控制器也被移动和可能的 Flash 客户端使用。【参考方案3】:

取决于你到底想达到什么目标:

创建一个返回正确视图的 ViewEngine 例如:http://www.hanselman.com/blog/ABetterASPNETMVCMobileDeviceCapabilitiesViewEngine.aspx

或者,您可以根据 URL 中的参数返回视图或 JSON

【讨论】:

【参考方案4】:

但我认为很多逻辑会 从 API 控制器复制。

我想你自己回答了这个问题。我会把它们放在同一个控制器中。 :)

【讨论】:

以上是关于ASP.NET MVC:让 AP​​I 控制器操作返回 View 和/或 JSON 是不是是一种好习惯的主要内容,如果未能解决你的问题,请参考以下文章

获取和发布到 ASP.NET MVC 中的相同控制器操作

ASP.NET MVC 和组件架构

理解ASP.NET MVC

如何在 ASP.NET MVC 中执行辅助操作(即计算字段)?

深入理解 ASP.NET MVC 上的 async/await

如何重定向到 ASP.NET MVC 中的上一个操作?