MVC WebApi高级自定义路由

时间:2019-06-20 20:31:42

标签: c# asp.net-mvc asp.net-core .net-core

我为此苦了一段时间。我在互联网上进行了搜索,没有找到任何解决方案。

我想用某种自定义路由创建一个webapi项目。使用VS 2019,项目是.NET Core 2.2上的ASP.NET WebApi类型。路由应如下所示:

基本应用程序必须位于类似于“ https://my.server.com/myapi”的网址上。将被调用的URL的格式为“ https://my.server.com/myapi/ {InstanceName} / {CommandName}?{customParams}”

我在项目中定义了一个控制器,我想将所有请求重定向到该控制器,其中instanceName可以是控制器中包含的所有方法的参数,因此我将获得该参数的值。根据MVC原则,CommandName与“动作” RouteData基本相同。如您所见,没有指定控制器,因为所有控制器都由一个控制器处理。

到目前为止,我已经尝试过这样的设置路由:

Startup.cs

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "MyRoute",
        template: "{instance}/{action}",
        defaults: new { controller = "MyController" });
    });
}

MyController.cs

[Route("/")]
[ApiController]
public class MyController : ControllerBase
{
    [HttpGet("{instance}/info")]
    public JsonResult Info(string instance, InfoCommand model)
    {
        // Just return serialized model for now.
        var result = new JsonResult(model);

        return result;
    }
}

但这不起作用。例如,当我打电话时,我从(我认为)网络服务器收到415响应

https://my.server.com/myapi/MYINSTANCE/info?param1=value1&param2=value2

从VS调试时,此URL如下所示:

https://localhost:12345/MYINSTANCE/info?param1=value1&param2=value2

但我认为路由无关紧要。

在最佳情况下(将[Route("{instance}")]放在控制器上方,将[HttpGet("info")]放在Info方法上方),我得到404的响应,这也是我所不希望的。

我什至尝试创建自己的ControllerFactory,但这也不起作用(在ControllerFactory的create方法内更改控制器,并向RouteData添加另一个参数)。

如何设置这样的路由?可能吗我仍然想使用所有其他MVC功能(模型绑定,正确的路由,身份验证功能等),这只是我无法弄清楚的路由。

1 个答案:

答案 0 :(得分:2)

您尝试得到415 Unsupported Media Type error的尝试是您最好的选择。
您只缺少FromQuery,如下所示。

该错误表明无法解析复杂类型InfoCommand
您必须指定必须从查询字符串中进行解析。

请注意,由于您使用的是基于属性的路由,因此通过MapRoute定义的路由无效。只是一个或另一个。

[Route("/")]
[ApiController]
public class MyController : ControllerBase
{
    [HttpGet("{instance}/info")]
    public JsonResult Info(string instance, [FromQuery] InfoCommand model)
    {
        var result = new JsonResult(model);
        return result;
    }
}

public class InfoCommand
{
    public InfoCommand()
    {}

    public string Param1 { get; set; }
    public string Param2 { get; set; }
}