解决MVC的Controller和Web API的Controller类名不能相同的问题
问题描述:
在Area的一个项目文件夹内,在Controller中我们要创建Mvc Controller及Api Controller,假如一个购物车的业务(shopcard)
mvc路由注册为~/{controller}/{action},我希望的访问地址应该是 ~/shopcard/action
api中由注册为~/api/{controller},我希望的访问地址应该是 ~/api/shopcard
那么问题就产生了,微软设计这个框架是通过类名去匹配的 mvc下你创建一个 shopcardController继承Controller,就不能再创建一个同名的shopcardController继承ApiController,这样的话mvc的访问地址和api的访问地址必须要有一个名字不能叫shopcard,不得不改名
问题原因:
通过查看微软System.Web.Http的源码,我们发现其实这个问题也很好解决,在这个DefaultHttpControllerSelector类中,微软有定义Controller的后缀
我们只要把ApiController的后缀改成和MVC不一样,就可以解决问题了。这个字段是个静态只读的Field,我们只要把它改成ApiContrller就解决问题了
解决方法:
可以利用反射解决这个问题,在注册Api路由前添加以下代码即可完成,代码如下:
var suffix = typeof(DefaultHttpControllerSelector).GetField("ControllerSuffix", BindingFlags.Static | BindingFlags.Public); if (suffix != null) suffix.SetValue(null, "ApiController");
demo
controller:
public class shopCardController : Controller { // GET: shop/shopCard [System.Web.Mvc.HttpGet] public ActionResult Index() { return View(); } } public class shopCardApiController:ApiController { [System.Web.Http.HttpGet] public string Get(string id) { return "test"; } }
webApi route:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服务 var suffix = typeof(DefaultHttpControllerSelector).GetField("ControllerSuffix", BindingFlags.Static | BindingFlags.Public); if (suffix != null) suffix.SetValue(null, "ApiController"); // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }