我正在创建一个新的MVC4项目,研究让我相信现在通过Web API框架而不是控制器操作可以更好地实现从javascript到服务器端的通信。我的理解是否正确?
我假设我可以在Web API和MVC控制器之间共享所有属性等,所以面对它,对我来说似乎不是一个巨大的变化。
当我设置应用程序时,我喜欢将组件拆分到项目中。我的计划是拥有一个MVC项目和一个Web API项目。但我遇到了问题。例如,我最终有2个应用程序,单独的路由设置等等。
所以我的问题是,在MVC应用程序中,Web API框架应该位于同一个项目中,还是应该将Web API分离为自己的项目并解决问题?
答案 0 :(得分:104)
不幸的是你错了 - 我假设我可以在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 API可以轻松地托管在与ASP.NET MVC相同的项目。
如果您要为您的在线服务构建适当的API(可能由外部客户或各种设备使用),例如为您的移动应用程序提供支持,我只会将Web API分离到单独的项目中。
答案 1 :(得分:27)
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
答案 2 :(得分:8)
经过一定程度的经验(为应用程序和mvc创建API)。我主要做两件事。
我为来自其他客户端或其他设备(Android / IOS应用程序)的api调用创建了一个单独的项目。其中一个原因是因为身份验证不同,它是基于令牌的(保持无状态)。我不想在我的MVC应用程序中混合使用它。
对于我的mvc应用程序的javascript / jquery api调用,我喜欢保持简单,所以我在我的MVC应用程序中包含了一个web api。我不打算在我的javascript api调用中使用基于令牌的身份验证,因为嘿,它在同一个应用程序中。我可以在API端点上使用[authorize]
属性,当用户未登录时,他将无法获取数据。
此外,在处理购物车并且您希望在会话中存储用户购物车时(未登录),如果您通过JavaScript代码添加/删除产品,则需要在API中使用此选项。这将使您的API确实有状态,但也会降低MVC-API的复杂性。
答案 3 :(得分:6)
答案 4 :(得分: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)。
答案 5 :(得分:2)
即使您的项目如此复杂以至于需要两个“前端”,我仍然只会考虑将webapi拆分为单独的项目作为最后的手段。您将面临部署难题,新手很难理解您的解决方案的结构。更不用说路由问题。
我的目标是将system.web名称空间保持在一个“表示层”中。尽管webapi不是 presentational ,但它仍然是应用程序界面的一部分。只要您保留域中的逻辑而不是控制器,就不应该遇到太多问题。另外,不要忘记使用区域。
答案 6 :(得分:0)
除了为Web.Api。
设置单独的DLL只是一个建议:
创建一个要在app_start上调用的类方法
[assembly:WebActivatorEx.PostApplicationStartMethod(typeof(API.AppWebActivator),“Start”)]
[assembly:WebActivatorEx.ApplicationShutdownMethod(typeof(API.AppWebActivator),“Shutdown”)]
在“开始方法”
中注册web.api路由public static void Start(){ GlobalConfiguration.Configure(WebApiConfig.Register); }
将项目引用到Web项目。激活开始方法。
希望这有帮助。
答案 7 :(得分:0)
我尝试将API控制器拆分为一个新项目。我所做的就是创建一个新的库项目,将控制器移到名为API的文件夹中。 然后将库项目的引用添加到MVC项目中。
webAPI配置保留在MVC项目中。它工作正常。