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


88

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

我假设我可以在Web API和MVC控制器之间共享我的所有属性,因此从表面上看,这对我来说似乎不是一个巨大的变化。

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

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

Answers:


110

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

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

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

最终,如果您要实现的全部目标就是采用一种“新的,新潮的”方式来提供JSON内容,请三思而后行。除非您真正考虑采用HTTP并以RESTful方式构建应用程序,否则我当然不建议重构任何现有代码。

这完全取决于您要构建的内容。如果您要开始一个新项目,而您只需要提供一些JSON来简化您的Web应用程序-如果您愿意使用一些可能重复的代码(例如我上面提到的内容),则可以轻松地将Web API托管在其中与ASP.NET MVC相同的项目。

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


2
+1出色的答案。我以为最初,MVC和WebAPI可能会共享一些代码,尤其是在过滤器,模型绑定等情况下,但是它们是完全不同的。
VJAI 2012年

5
是的,在这种情况下,只需在Visual Studio中启动一个新的MVC4项目,然后在提示您输入项目模板时(第二个屏幕),只需选择Web API。这将从Nuget安装Web API,并且在您描述的情况下应该很好。您得到的是插入Global.asax的单独的Web API配置文件。另外,您可能希望将API控制器分离到单独的文件夹中(默认情况下,它们与MVC控制器一起使用)。最后,默认路由显然是分开配置的,并且不会互相干扰
Filip W

9
我希望我的领导在他设计我们当前的项目之前会读过这篇文章。
Billdr

2
@FilipW感谢您的良好解释。我也有一个MVC应用程序,并将使用WebAPI2为Android应用程序使用服务。另一方面,正如David Peden所说,在决定为WebAPI创建新的单独项目时,安全性,维护和部署也非常重要。在这种情况下,请牢记它们,您会提出什么建议?要为WebAPI创建新的单独项目还是使用当前的MVC项目?提前致谢。
2015年

1
很好:“如果您要为在线服务构建适当的API(可能由外部客户或各种设备使用,例如为移动应用程序加油),我只会将Web API分离到一个单独的项目中。” 击中钉子的头部,可以轻松地确定采用哪种方法。
ozzy432836

27

IMO,安全性和部署将决定您的决定。例如,如果您的MVC应用程序使用Forms身份验证,但是您希望对API使用基本身份验证(带有SSL),那么单独的项目将使您的生活更轻松。如果您想将站点托管在www.example.com上,但将API托管为api.example.com(与www.example.com/api相对),则单独的项目将使您的生活更轻松。如果您将项目分开并进行相应的子域划分,并且打算从MVC应用程序中利用自己的API,则必须弄清楚如何在客户端调用API时处理“ 同源策略”问题。常见的解决方案是利用jsonpCORS(最好是可以的话)。

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


我正在努力解决将Web API与我的MVC应用程序集成或将其作为独立项目的决策问题。我能够将Web API HelloWorld应用程序成功部署到Web主机上的子域。在这个单独的项目中,我很可能会使用MVC Web应用程序中的模型,并在该单独的项目中调用代码。沿着单独的项目走这条路线似乎比较容易,但是您认为使用这种方法会遇到哪些问题?
Ciaran Gallagher

2
就个人而言,我不会将您的视图模型用作API的DTO。我希望这个决定会给您带来极大的痛苦,因为您的视图模型和API签名会有所不同。SoC(en.wikipedia.org/wiki/Separation_of_concerns)非常重要。
大卫·佩登

@DavidPeden您建议为WebAPI创建一个新的单独项目。真的吗?另一方面,我将为WebAPI创建一个新的单独项目(我的应用程序中目前有一个UI层(MVC)和数据层(类库)。因此,我也使用DI,但是我想知道是否可以使用在数据层中为新创建的WebAPI项目使用相同的实体,存储库,接口和抽象类,而我唯一要做的就是创建WebAPI控制器?还是我也创建它们(实体,存储库,接口和抽象类)?类),再次为的WebAPI任何帮助,请?
杰克

1
@ H.Johnson很难给出有意义的一般建议,但是听起来像您将从拥有一个封装了您的实体和存储库的应用程序服务层中受益,这两个UI(MVC和API)都可以利用。
大卫·佩登

9

经过一定程度的经验(为应用程序和mvc创建API)。我大部分都做。

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

对于我对mvc应用程序的javascript / jquery api调用,我想使事情保持简单,因此我在MVC应用程序中包含了一个Web API。我不想在我的javascript api调用中使用基于令牌的身份验证,因为嘿,它在同一应用程序中。我只能[authorize]在API端点上使用属性,当用户未登录时,他将不会获取数据。

此外,在处理购物车时,如果您想在会话中存储用户购物车(未登录),那么如果通过javascript代码添加/删除产品,则也需要在API中使用此功能。这将确保您的API处于有状态状态,但也将降低MVC-API的复杂性。


4
好吧,@ Dimi,这对于获得一些选票是无用的编辑……我如何拒绝这些选票?
CularBytes

做你想做的。我编辑不是通过投票,而是为了获得最佳效果。前进。
开发人员

3
@CularBytes您不能拒绝编辑,但是可以再次编辑并回滚更改。这需要少于2000个代表的同行评审过程,但是您有足够的代表可以立即进行。我同意该修改没有任何价值,并已为您回滚。
丹·贝查德


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)中。


2

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

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


1
我想要单独项目的主要原因是该API并不是真正的前端。是中间层。
lordcheeto 2014年

6
“新手很难理解”不是选择其中一种方法的重要理由。尽可能确保简单,但是复杂的需求通常需要复杂的解决方案。与其编写笨拙的代码来迎合新手,不如训练新手理解和编写智能代码。
Dan Bechard

0

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

只是一个建议:

  1. 创建项目
  2. 掘金WebActivatorEx
  3. 创建一个要在app_start上调用的类方法

    [程序集:WebActivatorEx.PostApplicationStartMethod(typeof(API.AppWebActivator),“开始”)]

    [assembly:WebActivatorEx.ApplicationShutdownMethod(typeof(API.AppWebActivator),“ Shutdown”)]

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

    公共静态无效Start(){GlobalConfiguration.Configure(WebApiConfig.Register); }

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

希望这可以帮助。


0

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.