单独项目中的 MVC 解决方案中的 Web API

Posted

技术标签:

【中文标题】单独项目中的 MVC 解决方案中的 Web API【英文标题】:Web API in MVC solution in separate project 【发布时间】:2012-10-06 00:19:54 【问题描述】:

我正在创建一个新的 MVC4 项目,研究使我相信现在通过 Web API 框架而不是控制器操作更好地实现从 javascript 到服务器端的通信。我的理解正确吗?

我假设我可以在 Web API 和 MVC 控制器之间共享我的所有属性等,所以从表面上看,这对我来说似乎并没有太大的变化。

在设置应用程序时,我喜欢将组件拆分到项目中。我的计划是有一个 MVC 项目和一个 Web API 项目。但我遇到了问题。例如,我最终得到了 2 个应用程序,单独的路由设置等。

所以我的问题是,在 MVC 应用程序中,Web API 框架应该位于同一个项目中,还是应该将 Web API 分离到自己的项目中并解决这些问题?

【问题讨论】:

【参考方案1】:

经过一定程度的经验(为应用程序和 mvc 创建 API)。我主要两者都做。

我为来自其他客户端或其他设备(android/ios 应用)的 api 调用创建了一个单独的项目。原因之一是因为身份验证不同,它是基于令牌的(使其保持无状态)。我不想在我的 MVC 应用程序中混用它。

对于我的 javascript/jquery api 调用我的 mvc 应用程序,我喜欢保持简单,所以我在我的 MVC 应用程序中包含一个 web api。我不打算使用我的 javascript api 调用进行基于令牌的身份验证,因为嘿,它在同一个应用程序中。我可以在 API 端点上使用 [authorize] 属性,当用户未登录时,他将无法获取数据。

此外,在处理购物车时,如果您想在会话中存储用户购物车(未登录时),如果您通过 javascript 代码添加/删除产品,您也需要在 API 中包含此内容。这肯定会使您的 API 有状态,但也会降低 MVC-API 的复杂性。

【讨论】:

好吧@Dimi,这是一个无用的编辑来获得一些选票......我怎么能拒绝这些? 做你想做的。我不是通过投票进行编辑,而是为了我认为的最佳外观。来吧。 @CularBytes 您不能拒绝编辑,但可以再次编辑并回滚更改。这需要一个低于 2,000 个代表的同行评审过程,但您有足够的代表立即完成。我同意修改没有增加任何价值,并已为您回滚。【参考方案2】:

我尝试将 API 控制器拆分为一个新项目。我所做的只是创建一个新的库项目,将控制器移动到名为 API 的文件夹中。 然后将库项目的引用添加到MVC项目中。

webAPI 配置保留在 MVC 项目本身中。它工作正常。

【讨论】:

【参考方案3】:

不幸的是,你错了 - 我假设我可以在 web api 和 mvc 控制器之间共享我的所有属性等,所以从表面上看,这对我来说似乎不是一个巨大的变化。

Web API 和 MVC 使用的许多概念,尽管乍一看很相似,但实际上并不兼容。例如,Web API 属性为System.Web.Http.Filters.Filter,MVC 属性为System.Web.Mvc.Filter - 它们不可互换。

同样适用于许多其他概念 - 模型绑定(完全不同的机制)、路由(Web API 使用 HTTPRoutes 而不是路由,即使它们都在相同的底层 RouteTable 上运行)、依赖解析器(不兼容)等等 - 即使表面上相似,实践中却大相径庭。而且,Web API 没有区域的概念。

最终,如果您想要实现的只是拥有一种“新潮、新潮”的方式来提供 JSON 内容,那么在走这条路之前请三思。我当然不建议重构任何现有代码,除非您真的在考虑采用 HTTP 并以 RESTful 方式构建您的应用程序。

这完全取决于您要构建的内容。如果您正在开始一个新项目,并且您所需要的只是提供一些 JSON 来促进您的 Web 应用程序 - 只要您愿意使用一些可能重复的代码(就像我上面提到的东西),Web API 可以很容易地托管在与 ASP.NET MVC 相同的项目。

如果您要为您的在线服务构建适当的 API(可能供外部客户或各种设备使用)(例如为您的移动应用程序提供燃料),我只会将 Web API 分离到一个单独的项目中。

【讨论】:

+1 很好的答案。我最初认为 MVC 和 WebAPI 可能会共享一些代码,尤其是在过滤器、模型绑定等情况下,但它们完全不同。 是的,在这种情况下,只需在 Visual Studio 中启动一个新的 MVC4 项目,当提示输入项目模板(第二个屏幕)时,只需选择 Web API。这将从 Nuget 安装 Web API,在您描述的情况下应该非常好。你得到的是插入 Global.asax 的单独的 Web API 配置文件。此外,您可能希望将 API 控制器分离到单独的文件夹中(默认情况下它们与 MVC 控制器一起)。最后,默认路由明明是单独配置的,互不干扰 我希望我的负责人在设计我们当前的项目之前能够阅读这篇文章。 @FilipW 感谢您的精彩解释。我还有一个 MVC 应用程序,并将使用 WebAPI2 为 Android 应用程序使用服务。另一方面,正如 David Peden 在下面所说,在决定为 WebAPI 创建一个新的独立项目时,安全性、维护和部署 也非常重要。在那种情况下,记住他们,你会建议什么?为 WebAPI 创建一个新的单独项目或使用当前的 MVC 项目?提前致谢。 非常好“如果您要为您的在线服务构建适当的 API,我只会将 Web API 分离到一个单独的项目中 - 可能供外部客户或各种设备使用 - 例如为您的移动应用程序加油。”一针见血,很容易确定采用哪种方法。【参考方案4】:

除了为 Web.Api 设置单独的 DLL。

只是一个建议:

    创建项目 Nugget WebActivatorEx

    创建一个在 app_start 时调用的类方法

    [程序集:WebActivatorEx.PostApplicationStartMethod(typeof(API.AppWebActivator),"Start")]

    [程序集:WebActivatorEx.ApplicationShutdownMethod(typeof(API.AppWebActivator), "Shutdown")]

    在 Start 方法中注册一个 web.api 路由

    公共静态无效开始() GlobalConfiguration.Configure(WebApiConfig.Register);

    将项目引用到 Web 项目。激活启动方法。

希望这会有所帮助。

【讨论】:

【参考方案5】:

我最近做了几乎相同的事情:我从一个新的 MVC 4 Web 应用程序项目开始,选择 VS2012 中的 Web API 模板。

这将创建一个托管在与 MVC 相同的应用程序中的 Web API。

我想将 ApiControllers 移动到一个单独的类库项目中。这相当容易,但解决方案有点隐藏。

在 MVC 4 项目的 AssemblyInfo.cs 中添加类似的代码行

[assembly: PreApplicationStartMethod(typeof(LibraryRegistrator), "Register")]

现在您需要类 LibraryRegistrator(随便命名)

public class LibraryRegistrator
    
        public static void Register()
        
            BuildManager.AddReferencedAssembly(Assembly.LoadFrom(HostingEnvironment.MapPath("~/bin/yourown.dll")));
        
    

在 MVC 4 项目中还添加对 Api 库的引用。

现在您可以将 Api 控制器添加到您自己的单独类库 (yourown.dll) 中。

【讨论】:

【参考方案6】:

来自 SimpleInjector(IoC 框架)的 Steven 为两个独立的项目提供建议:What is the difference between DependencyResolver.SetResolver and HttpConfiguration.DependencyResolver in WebAPI

【讨论】:

【参考方案7】:

IMO、安全性和部署应该推动您做出决定。例如,如果您的 MVC 应用程序使用表单身份验证,但您有兴趣为 API 使用基本身份验证(使用 SSL),那么单独的项目将使您的生活更轻松。如果您想在 www.example.com 托管您的站点,但将您的 API 托管为 api.example.com(与 www.example.com/api 相比),单独的项目将使您的生活更轻松。如果您将项目和子域相应地分开,并且您打算从 MVC 应用程序中利用自己的 API,那么您将必须弄清楚如何处理客户端调用 API 的Same Origin Policy 问题。对此的常见解决方案是利用jsonp 或CORS(如果可以的话最好)。

更新(2013 年 3 月 26 日):官方 CORS 支持即将到来:http://aspnetwebstack.codeplex.com/wikipage?title=CORS%20support%20for%20ASP.NET%20Web%20API

【讨论】:

我正在努力解决有关将 Web API 与我的 MVC 应用程序集成或将其作为一个单独的项目的决定的问题。我能够成功地将 Web API HelloWorld 应用程序部署到我的网络主机上的子域。在这个单独的项目中,我可能会使用我的 MVC Web 应用程序中的模型并调用该单独项目中的代码。似乎沿着单独项目的这条路线走下去可能更容易,但你认为我用这种方法会遇到什么问题? 就个人而言,我不会将您的视图模型用作 API 的 DTO。我希望随着您的视图模型和 API 签名的分歧,这个决定会给您带来一些严重的痛苦。 SoC (en.wikipedia.org/wiki/Separation_of_concerns) 非常重要。 @DavidPeden 您建议为 WebAPI 创建一个新的单独项目。真的吗?另一方面,我将为 WebAPI 创建一个新的单独项目(我的应用程序中目前有一个 UI 层(MVC)和数据层(类库)。所以,我也使用 DI,但我想知道是否可以使用新创建的 WebAPI 项目的数据层中的相同实体、存储库、接口和抽象类,我唯一​​要做的就是创建 WebAPI 控制器?还是我也创建所有它们(实体、存储库、接口和抽象类)再次用于 WebAPI?有什么帮助吗? @H.Johnson 很难给出有意义的一般建议,但听起来你会受益于拥有一个应用程序服务层,它封装了你的实体和存储库,你的两个 UI 都可以利用( MVC 和 API)。【参考方案8】:

即使您的项目如此复杂以至于需要两个“前端”,那么我仍然只会考虑将 webapi 拆分为一个单独的项目作为最后的手段。您将遇到部署难题,并且新手很难理解您的解决方案的结构。更不用说路由问题了。

我的目标是将 system.web 命名空间隔离在一个“表示层”中。尽管 webapi 不是 presentational,但它仍然是应用程序界面的一部分。只要您将逻辑保留在域中而不是控制器中,就不会遇到太多问题。另外,不要忘记使用区域。

【讨论】:

我想要单独项目的主要原因是 API 并不是真正的前端。它是中间层。 “新手很难理解”并不是选择一种方法而不是另一种方法的重要理由。当然,尽可能保持简单,但复杂的需求通常需要复杂的解决方案。我们应该训练新手理解和编写智能代码,而不是编写愚蠢的代码来迎合新手。

以上是关于单独项目中的 MVC 解决方案中的 Web API的主要内容,如果未能解决你的问题,请参考以下文章

前端 ASP.NET MVC4 作为一个项目,ASP.NET Web API 作为同一解决方案中的另一个项目 - 如何从前端调用 WebAPI?

集成 Web API 和 .net MVC 项目 (C#)

一个项目中的 Web API 和 Web 应用程序与单独的项目

如何使用标题中的两个参数和正文中的第二个参数从另一个 MVC 项目调用 Web API

如何从 ASP.NET 核心 mvc 向 asp.net 核心中的 Web API 发出 PUT 请求?

Web API 中的 MVC-6 与 MVC-5 BearerAuthentication