asp.net-mvc - 在单个根文件夹下组织 WebApi 控制器并路由到它们
问题描述
背景
在大多数应用程序中MVC
,WebApi
我们通常会看到以下结构:
/Controllers
HomeController.cs
/Models
通常这是从 MVC 模板生成的。
这将生成一个路由映射Startup.cs
:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
增加了复杂性
当我们向其中添加其他部分(例如自定义 ActionResults、Filters和 Areas 等)时,我们的 Web 应用程序真正开始变得越来越复杂。突然之间,即使组织得很好,顶层文件夹也会感觉有点混乱。
问题
通常,当我们添加Area
开箱即用时,会创建一个名为 Areas 的新顶级文件夹。
我的偏好是将所有与控制器相关的功能都移到其中的项目文件夹,例如 api 文件夹。
例如:
/api
/Home
/Controllers
HomeController.cs
/Models
/SomeArea1
/Controllers
/Models
这里的问题是现在您需要更改路由配置并在路由中包含 api - 这是我不想要的。
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
是否可以在项目中具有上述文件夹结构并具有如下路径?
http://localhost/ maps to /api/Home
http://localhost/customer maps to /api/Customer
解决方案
从 Mads 提供的有关控制器路由的部分(请参阅此处 - 自定义路由)
命名空间路由约定.cs
public class NamespaceRoutingConvention : IControllerModelConvention
{
private readonly string _baseNamespace;
public NamespaceRoutingConvention(string baseNamespace)
{
_baseNamespace = baseNamespace;
}
public void Apply(ControllerModel controller)
{
var hasRouteAttributes = controller.Selectors.Any(selector =>
selector.AttributeRouteModel != null);
if (hasRouteAttributes)
{
// This controller manually defined some routes, so treat this
// as an override and not apply the convention here.
return;
}
// Use the namespace and controller name to infer a route for the controller.
//
// Example:
//
// controller.ControllerTypeInfo -> "My.Application.Admin.UsersController"
// baseNamespace -> "My.Application"
//
// template => "Admin/[controller]"
//
// This makes your routes roughly line up with the folder structure of your project.
//
if (controller.ControllerType.Namespace == null)
return;
var template = new StringBuilder(GetControllerNamespace(controller.ControllerType.Namespace));
template.Replace('.', '/');
template.Append("/[controller]");
foreach (var selector in controller.Selectors)
{
selector.AttributeRouteModel = new AttributeRouteModel()
{
Template = template.ToString()
};
}
}
private string GetControllerNamespace(string controllerNamespace)
{
return controllerNamespace == _baseNamespace
? ""
: controllerNamespace.Substring(
_baseNamespace.Length + 1,
controllerNamespace.Length -
_baseNamespace.Length - 1);
}
}
启动.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
options.Conventions.Add(new NamespaceRoutingConvention("Enter the route namespace of the api folder")))
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
api 文件夹结构
在 API 文件夹下,我现在具有以下结构:
/api
/Ploop
HelloController.cs
HelloController.cs
TestController.cs
示例控制器代码
所以每个控制器代码如下所示:
public class HelloController : ControllerBase
{
[HttpGet]
public JsonResult Index()
{
return new JsonResult(new
{
message = "hello from XXX controller"
});
}
[HttpGet("{id?}")]
public JsonResult Index(int? id)
{
return new JsonResult(new
{
message = "Hello from XXX controller with index",
id
});
}
}
调用控制器
因此,当我们调用每个控制器时,我们会在浏览器中得到以下输出:
api/Ploop/HelloController.cs
http://localhost:51248/Ploop/Hello
{"message":"Hello from Ploop HelloController"}
http://localhost:51248/Ploop/Hello/12
{"message":"Hello from Ploop HelloController with index","id":12}
api/HelloController.cs
{"message":"Hello from root HelloController"}
http://localhost:51248/Hello/12
{"message":"Hello from root HelloController with index","id":12}
api/TestController.cs
{"message":"Hello from TestController"}
http://localhost:51248/Test/12
{"message":"Hello from TestController with index","id":12}
推荐阅读
- apache-spark - 在pyspark中加载超过54位小数的double类型时如何避免精度损失
- c++ - c ++函数模板别名长参数?
- python - 计算三维数据数组(纬度、经度、时间)中最长的连续值序列
- java - io.vertx.core.buffer.impl.VertxUnsafeHeapByteBuf 类无法访问其超类 io.netty.buffer.UnpooledUnsafeHeapByteBuf
- api - 如何在 Swagger 中记录 webhook?
- c - 调用8259A的时钟中断0x20中断时,跳转到0xf000:fff0
- opencv - imagemagick“convert -auto-gamma auto-level -normalize”命令的等效openCV代码?
- django-models - 防止模型中的条目将自身添加到 many2many 关系中
- javascript - 如何为服务器通道 discord.js 设置 mongo.db
- python - 带有一组工作音乐命令的小型不和谐机器人,大约 6 天前,播放功能完全停止运行(更多下文)