ASP.Net 路由参数的 MVC RouteAttribute 错误

ASP.Net MVC RouteAttribute Error with Route Parameter

我在尝试将路由映射添加到特定操作时遇到了很多不同的错误!

我正在尝试为 GET /Admin/Users/User/1 获取这条路线 和 POST /Admin/Users/User

但遗憾的是控制器中已经有一个用户属性! 所以我不能使用 public ActionResult User(long id) 因为我需要隐藏用户 属性 (我需要保留因为它是控制器的 IPrincipal 并且我仍然得到相同的错误)。

这样定义路由:

// First in RouteConfig
routes.MapMvcAttributeRoutes();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

// Then i'm registering my Areas.

此控制器位于管理区域。 用户控制器:控制器

[HttpGet]
[Route(Name = "User/{id:long}")]
public ActionResult GetUser(long id)
{
    var model = new UserViewModel
    {
        User = _usersService.GetUser(id),
        Roles = _rolesService.GetRoleDropdown()
    };

    return View("User");
}

[HttpPost]
[Route(Name = "User")]
public ActionResult GetUser(UserViewModel model)
{
    if (ModelState.IsValid)
    {
        _usersService.UpdateUserRoles(model.User);
        return RedirectToAction("Index");
    }

    return View("User", model);
}

这是我遇到的错误:

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int64' for method 'System.Web.Mvc.ActionResult User(Int64)' in 'MyProjectName.Web.Areas.Admin.Controllers.UsersController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters

我不确定是否真的理解错了!

我检查了这个解释属性的页面,没有发现任何问题 https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

编辑 1

还是不行,我把注册改成了

routes.MapMvcAttributeRoutes();

AreaRegistration.RegisterAllAreas();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

这是我的完整控制器代码,因为现在它不适用于初始代码中没有的索引操作。

[RouteArea("Admin")]
[RoutePrefix("Users")]
public class UsersController : Controller
{
    private readonly IUsersService _usersService;
    private readonly IRolesService _rolesService;

    public UsersController(
        IUsersService usersService,
        IRolesService rolesService)
    {
        _usersService = usersService;
        _rolesService = rolesService;
    }

    [HttpGet]
    [Route(Name = "Index")]
    public ActionResult Index()
    {
        var model = new UsersViewModel
        {
            Users = _usersService.GetUsers()
        };

        return View(model);
    }

    [HttpGet]
    [Route(Name = "User/{id:long}")]
    public new ActionResult User(long id)
    {
        var model = new UserViewModel
        {
            User = _usersService.GetUser(id),
            Roles = _rolesService.GetRoleDropdown()
        };

        return View("User");
    }

    [HttpPost]
    [Route(Name = "User")]
    public new ActionResult User(UserViewModel model)
    {
        if (ModelState.IsValid)
        {
            _usersService.UpdateUserRoles(model.User);
            return RedirectToAction("Index");
        }

        return View("User", model);
    }
}

现在,我正在尝试执行索引操作:

The current request is ambiguous between the following action methods: System.Web.Mvc.ActionResult Index() on type EspaceBiere.Web.Areas.Admin.Controllers.UsersController System.Web.Mvc.ActionResult User(Int64) on type EspaceBiere.Web.Areas.Admin.Controllers.UsersController System.Web.Mvc.ActionResult User(EspaceBiere.Web.Areas.Admin.ViewModels.Users.UserViewModel) on type EspaceBiere.Web.Areas.Admin.Controllers.UsersController

这是在尝试转到用户操作时进行的

A public action method 'User' was not found on controller 'EspaceBiere.Web.Areas.Admin.Controllers.UsersController'.

而我对索引操作的 link 是:

尝试使用 /Admin/Users 进行我的 Index 操作

尝试使用 /Admin/Users/User/1 进行 User 操作

编辑 2

好的,我的索引现在运行良好,但我的用户操作仍然无效! 我删除了 RouteAttribute 的所有 Name 属性以将它们保留在构造函数中(作为模板)-> [Route("User/{id:long}")]

抱歉,如果我第一次阅读时没有看到它们!

这里是 link 动作

                    <a href="@Url.Action("User", "Users", new { Area = "Admin", id = user.UserId })" class="btn btn-warning">
                    <i class="fa fa-pencil"></i>
                </a>

这里是错误

No matching action was found on controller 'EspaceBiere.Web.Areas.Admin.Controllers.UsersController'. This can happen when a controller uses RouteAttribute for routing, but no action on that controller matches the request.

如果我在 URL /Admin/Users/User/1 中写入它确实有效 那我应该怎么写 Url.Action ?

如果您打算使用属性路由,那么您还没有完全理解使用属性路由的概念。以下是如何配置所需路由的示例。

[RouteArea("Admin")]
[RoutePrefix("Users")]
public class UsersController : Controller {
    private readonly IUsersService _usersService;
    private readonly IRolesService _rolesService;

    public UsersController(
        IUsersService usersService,
        IRolesService rolesService) {
        _usersService = usersService;
        _rolesService = rolesService;
    }

    //GET Admin/Users
    //GET Admin/Users/Index
    [HttpGet]
    [Route("")]
    [Route("Index")]
    public ActionResult Index() {
        var model = new UsersViewModel {
            Users = _usersService.GetUsers()
        };

        return View(model);
    }

    //GET Admin/Users/User/1
    [HttpGet]
    [Route("User/{id:long}", Name = "GetUser")]
    public ActionResult GetUser(long id) {
        var model = new UserViewModel {
            User = _usersService.GetUser(id),
            Roles = _rolesService.GetRoleDropdown()
        };

        return View("User");
    }

    //POST Admin/Users/User
    [HttpPost]
    [Route("User")]
    public ActionResult PostUser(UserViewModel model) {
        if (ModelState.IsValid) {
            _usersService.UpdateUserRoles(model.User);
            return RedirectToAction("Index");
        }

        return View("User", model);
    }
}

If you are using both Areas with route attributes, and areas with convention based routes (set by an AreaRegistration class), then you need to make sure that area registration happen after MVC attribute routes are configured, however before the default convention-based route is set. The reason is that route registration should be ordered from the most specific (attributes) through more general (area registration) to the mist generic (the default route) to avoid generic routes from “hiding” more specific routes by matching incoming requests too early in the pipeline.

// First in RouteConfig
routes.MapMvcAttributeRoutes();

// Then register Areas.
AreaRegistration.RegisterAllAreas();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Route Names

You can specify a name for a route, in order to easily allow URI generation for it. For example, for the following route:

[Route("User/{id:long}", Name = "GetUser")]
public ActionResult GetUser(long id)

您可以使用 Url.RouteUrl:

生成 link
<a href="@Url.RouteUrl("GetUser", new { Area = "Admin", id = user.UserId })" class="btn btn-warning">
    <i class="fa fa-pencil"></i>
</a>

不错,

    [HttpPost]
    [Route("User")]
    public ActionResult PostUser(UserViewModel model) {
        if (ModelState.IsValid) {
            _usersService.UpdateUserRoles(model.User);
            return RedirectToAction("Index");
        }enter code here

        return View("User", model);
    }