带有路由参数的ASP.Net MVC RouteAttribute错误 [英] ASP.Net MVC RouteAttribute Error with Route Parameter

查看:95
本文介绍了带有路由参数的ASP.Net MVC RouteAttribute错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试将路由映射添加到某个动作时,我遇到许多不同的错误!

我正在尝试为 GET/Admin/Users/User/1 获得此路线和 POST/Admin/Users/User

但是很遗憾,Controller中已经有一个User属性!所以我不能使用 public ActionResult User(long id),因为我需要隐藏用户属性(我需要保留该属性,因为它是Controller的IPrincipal,并且仍然会出现相同的错误).

以这种方式定义路线:

 //首先在RouteConfig中route.MapMvcAttributeRoutes();route.MapRoute(名称:默认",url:"{controller}/{action}/{id}",默认值:new {controller ="Home",action ="Index",id = UrlParameter.Optional});//然后,我正在注册我的区域. 

此控制器在管理区域"中.UsersController:控制器

  [HttpGet][Route(Name ="User/{id:long}")]公共ActionResult GetUser(长ID){var model = new UserViewModel{用户= _usersService.GetUser(id),角色= _rolesService.GetRoleDropdown()};返回View("User");}[HttpPost][Route(Name ="User")]公共ActionResult GetUser(UserViewModel模型){如果(ModelState.IsValid){_usersService.UpdateUserRoles(model.User);返回RedirectToAction("Index");}返回View("User",model);} 

这是我遇到的错误:

 参数字典在'MyProjectName.Web.Areas'中为方法'System.Web.Mvc.ActionResult User(Int64)'包含参数'id'的空条目,该参数'id为非空类型'System.Int64'.Admin.Controllers.UsersController".可选参数必须是引用类型,可为空的类型,或者必须声明为可选参数.参数名称:参数 

我不确定自己到底是怎么了!

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

编辑1

它仍然不起作用,我将注册更改为

  routes.MapMvcAttributeRoutes();AreaRegistration.RegisterAllAreas();route.MapRoute(名称:默认",url:"{controller}/{action}/{id}",默认值:new {controller ="Home",action ="Index",id = UrlParameter.Optional}); 

这是我的完整控制器代码,因为现在它不适用于不在初始代码中的Index动作.

  [RouteArea("Admin")][RoutePrefix(用户")]公共类UsersController:控制器{私有只读IUsersService _usersService;私有只读IRolesService _rolesService;公共UsersController(IUsersService usersService,IRolesService roleService){_usersService = usersService;_rolesService = RolesService;}[HttpGet][Route(Name ="Index")]公共ActionResult Index(){var model = new UsersViewModel{用户= _usersService.GetUsers()};返回View(model);}[HttpGet][Route(Name ="User/{id:long}")]公开新的ActionResult用户(长ID){var model = new UserViewModel{用户= _usersService.GetUser(id),角色= _rolesService.GetRoleDropdown()};返回View("User");}[HttpPost][Route(Name ="User")]公开新的ActionResult用户(UserViewModel模型){如果(ModelState.IsValid){_usersService.UpdateUserRoles(model.User);返回RedirectToAction("Index");}返回View("User",model);}} 

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

当前请求在以下操作方法之间是不明确的:类型上的System.Web.Mvc.ActionResult Index()EspaceBiere.Web.Areas.Admin.Controllers.UsersControllerSystem.Web.Mvc.ActionResult用户(Int64)的类型EspaceBiere.Web.Areas.Admin.Controllers.UsersControllerSystem.Web.Mvc.ActionResult用户(EspaceBiere.Web.Areas.Admin.ViewModels.Users.UserViewModel)在键入EspaceBiere.Web.Areas.Admin.Controllers.UsersController

,而在尝试执行用户操作时会显示此信息

在控制器上未找到公共操作方法用户""EspaceBiere.Web.Areas.Admin.Controllers.UsersController".

我到index动作的链接是:

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

尝试对 User 操作

使用/Admin/Users/User/1

编辑2

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

对不起,如果我在第一次阅读时没有看到它们!

这是动作的链接

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

这是错误

 在控制器'EspaceBiere.Web.Areas.Admin.Controllers.UsersController'上找不到匹配的动作.当控制器使用RouteAttribute进行路由,但该控制器上没有任何操作与请求匹配时,可能会发生这种情况. 

如果我在URL/Admin/Users/User/1中写入,它确实可以工作那我该怎么写我的Url.Action?

解决方案

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

  [RouteArea("Admin")][RoutePrefix(用户")]公共类UsersController:控制器{私有只读IUsersService _usersService;私有只读IRolesService _rolesService;公共UsersController(IUsersService usersService,IRolesService roleService){_usersService = usersService;_rolesService = RolesService;}//获取管理员/用户//获取管理员/用户/索引[HttpGet][路线("")][Route("Index")]public ActionResult Index(){var model = new UsersViewModel {用户= _usersService.GetUsers()};返回View(model);}//GET Admin/Users/User/1[HttpGet][Route("User/{id:long}",Name ="GetUser")]public ActionResult GetUser(long id){var model = new UserViewModel {用户= _usersService.GetUser(id),角色= _rolesService.GetRoleDropdown()};返回View("User");}//POST管理员/用户/用户[HttpPost][Route("User")]public ActionResult PostUser(UserViewModel model){如果(ModelState.IsValid){_usersService.UpdateUserRoles(model.User);返回RedirectToAction("Index");}返回View("User",model);}} 

如果您同时使用具有路线属性的区域和同时具有以下属性的区域基于约定的路由(由AreaRegistration类设置),然后您需要确保区域注册发生在MVC属性之后路由已配置,但是在基于默认约定的配置之前路线已设定.原因是应该订购路线注册从最具体的(属性)到更一般的(区域)注册)到Mist通用(默认路由)以避免通用通过匹配传入来从隐藏"更具体的路由中选择路由在管道中过早提出请求.

 //首先在RouteConfig中route.MapMvcAttributeRoutes();//然后注册区域.AreaRegistration.RegisterAllAreas();route.MapRoute(名称:默认",url:"{controller}/{action}/{id}",默认值:new {controller ="Home",action ="Index",id = UrlParameter.Optional}); 

路由名称

您可以为路由指定名称,以便轻松允许URI它的一代.例如,对于以下路线:

  [Route("User/{id:long}",Name ="GetUser")]公共ActionResult GetUser(长ID) 

您可以使用 Url.RouteUrl 生成链接:

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

I'm getting a lot of different errors while trying to add Route mapping to a certain action!

I'm trying to get this route for GET /Admin/Users/User/1 and POST /Admin/Users/User

But sadly there is already a User property in Controller! So i cannot use public ActionResult User(long id) because i need to hide the user property (that i need to keep because it's the IPrincipal of the Controller and i still get the same error).

Defining route this way :

// 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.

this controller is in Admin Areas. UsersController : Controller

[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);
}

Here is the error i'm getting :

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

I'm not sure to really understand what's wrong!

I checked this page that explain the attributes and i see nothing wrong https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

EDIT 1

It still doesn't work, i changed my registration to

routes.MapMvcAttributeRoutes();

AreaRegistration.RegisterAllAreas();

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

Here is my full controller code because now it doesn't work for my Index action that was not in the initial code.

[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);
    }
}

Now, i'm getting while trying to go to my index action:

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

and this while trying to go to User Action

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

And my link to the index action was :

tried with /Admin/Users for my Index Action

tried with /Admin/Users/User/1 for User Action

EDIT 2

Ok, my index is now working perfectly, but my user action still is not working! I've removed all the Name properties of the RouteAttribute to keep them in the constructor (as template) -> [Route("User/{id:long}")]

Sorry, if i didn't see them on first read!

Here is the link to the action

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

Here is the error

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.

It does work if i write in the URL /Admin/Users/User/1 So how should i write my Url.Action ?

解决方案

You haven't completely understood the concept of using attribute routing if that was your intention. Here is an example of how to configure the routes you wanted.

[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)

you could generate a link using Url.RouteUrl:

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

这篇关于带有路由参数的ASP.Net MVC RouteAttribute错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆